+ * class members and bytecode behaviors
+ * can break down in a few ways:
+ *
* - If {@code C} is not symbolically accessible from the lookup class's loader,
* the lookup can still succeed, even when there is no equivalent
* Java expression or bytecoded constant.
@@ -280,7 +304,8 @@
* A lookup can fail, because
* the containing class is not accessible to the lookup class, or
* 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
* thrown from the attempted lookup. The exact class will be one of
* the following:
@@ -291,14 +316,23 @@
*
*
* In general, the conditions under which a method handle may be
- * looked up for a method {@code M} are exactly equivalent to the conditions
- * under which the lookup class could have compiled and resolved a call to {@code M}.
+ * looked up for a method {@code M} are no more restrictive than the conditions
+ * 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},
* a method handle lookup will generally raise a corresponding
* checked exception, such as {@code NoSuchMethodException}.
* 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 exactly equivalent
+ * to executing the compiled, verified, and resolved call to {@code M}.
* The same point is true of fields and constructors.
+ *
+ * Discussion:
+ * 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.
*
* 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
@@ -312,6 +346,12 @@
* (which will necessarily be a superclass of the lookup class)
* to the lookup class itself.
*
+ * The JVM imposes a similar requirement on {@code invokespecial} instruction,
+ * that the receiver argument must match both the resolved method and
+ * 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.)
+ *
* The JVM represents constructors and static initializer blocks as internal methods
* with special names ({@code ""} and {@code ""}).
* The internal syntax of invocation instructions allows them to refer to such internal
@@ -331,6 +371,43 @@
* which can transform a lookup on {@code C.E} into one on any of those other
* classes, without special elevation of privilege.
*
+ * 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.
+ *
+ *
+ *
+ * Discussion of private access:
+ * We say that a lookup has private access
+ * 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:
+ *
+ * - access private fields, methods, and constructors of the lookup class
+ *
- create method handles which invoke caller sensitive methods,
+ * such as {@code Class.forName}
+ *
- create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
+ *
- avoid package access checks
+ * for classes accessible to the lookup class
+ *
- create {@link Lookup#in delegated lookup objects} which have private access to other classes
+ * within the same package member
+ *
+ *
+ * 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 bytecode behaviors and Java language access permissions
+ * can be reliably determined and emulated by method handles.
+ *
+ *
Security manager interactions
* Although bytecode instructions can only refer to classes in
* a related class loader, this API can search for methods in any
* class, as long as a reference to its {@code Class} object is
@@ -343,16 +420,6 @@
* and the Core Reflection API
* (as found on {@link java.lang.Class Class}).
*
- * 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.
- *
- *
Security manager interactions
- *
* If a security manager is present, member lookups are subject to
* additional checks.
* From one to three calls are made to the security manager.
@@ -365,19 +432,22 @@
* member is actually defined.
* The value {@code lookc} is defined as not present
* if the current lookup object does not have
- * {@linkplain java.lang.invoke.MethodHandles.Lookup#PRIVATE private access}.
+ * private access.
* The calls are made according to the following rules:
*
- * - If {@code lookc} is not present, or if its class loader is not
+ *
- Step 1:
+ * 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},
* then {@link SecurityManager#checkPackageAccess
* smgr.checkPackageAccess(refcPkg)} is called,
* where {@code refcPkg} is the package of {@code refc}.
- *
- If the retrieved member is not public and
+ *
- Step 2:
+ * If the retrieved member is not public and
* {@code lookc} is not present, then
* {@link SecurityManager#checkPermission smgr.checkPermission}
* with {@code RuntimePermission("accessDeclaredMembers")} is called.
- *
- If the retrieved member is not public,
+ *
- Step 3:
+ * If the retrieved member is not public,
* and if {@code lookc} is not present,
* and if {@code defc} and {@code refc} are different,
* then {@link SecurityManager#checkPackageAccess
@@ -408,11 +478,32 @@
* In cases where the lookup object is
* {@link MethodHandles#publicLookup() publicLookup()},
* or some other lookup object without
- * {@linkplain java.lang.invoke.MethodHandles.Lookup#PRIVATE private access},
+ * private access,
* the lookup class is disregarded.
* In such cases, no caller-sensitive method handle can be created,
* access is forbidden, and the lookup fails with an
* {@code IllegalAccessException}.
+ *
+ * Discussion:
+ * 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.
+ *
+ * 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.
+ *
+ * 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
class Lookup {
@@ -639,7 +730,7 @@
* (Since static methods do not take receivers, there is no
* additional receiver argument inserted into the method handle type,
* 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.
*
* The returned method handle will have
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
@@ -679,7 +770,7 @@
* Produces a method handle for a virtual method.
* The type of the method handle will be that of the method,
* 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.
*
* When called, the handle will treat the first argument as a receiver
* and dispatch on the receiver's type to determine which method
@@ -696,7 +787,7 @@
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
* the method's variable arity modifier bit ({@code 0x0080}) is set.
*
- * Because of the general equivalence between {@code invokevirtual}
+ * Because of the general equivalence between {@code invokevirtual}
* instructions and method handles produced by {@code findVirtual},
* if the class is {@code MethodHandle} and the name string is
* {@code invokeExact} or {@code invoke}, the resulting
@@ -770,10 +861,10 @@
* the constructor of the specified type.
* 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.
- * 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.
*
- * (Note: The requested type must have a return type of {@code void}.
- * This is consistent with the JVM's treatment of constructor type descriptors.)
+ * The requested type must have a return type of {@code void}.
+ * (This is consistent with the JVM's treatment of constructor type descriptors.)
*
* The returned method handle will have
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
@@ -817,27 +908,26 @@
}
/**
- * Produces an early-bound method handle for a virtual method,
- * as if called from an {@code invokespecial}
- * instruction from {@code caller}.
+ * Produces an early-bound method handle for a virtual method.
+ * It will bypass checks for overriding methods on the receiver,
+ * as if called from an {@code invokespecial}
+ * instruction from within the explicitly specified {@code specialCaller}.
* 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
- * to the caller.
+ * to the lookup object.
*
- * When called, the handle will treat the first argument as a receiver,
- * but will not dispatch on the receiver's type.
- * (This direct invocation action is identical with that performed by an
- * {@code invokespecial} instruction.)
- *
- * If the explicitly specified caller class is not identical with the
- * lookup class, or if this lookup object does not have private access
+ * Before method resolution,
+ * 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.
*
* The returned method handle will have
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
* the method's variable arity modifier bit ({@code 0x0080}) is set.
- *
+ *
* (Note: JVM internal methods named {@code ""} are not visible to this API,
* even though the {@code invokespecial} instruction can refer to them
* in special circumstances. Use {@link #findConstructor findConstructor}
@@ -993,7 +1083,7 @@
* Produces an early-bound method handle for a non-static 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.
- * 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,
* without any insertion of an additional receiver parameter.
* The given receiver will be bound into the method handle,
@@ -1008,17 +1098,17 @@
* the given receiver value will be bound to it.)
*
* This is equivalent to the following code:
- *
+ * {@code
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
-MethodHandle mh0 = lookup().{@link #findVirtual findVirtual}(defc, name, type);
-MethodHandle mh1 = mh0.{@link MethodHandle#bindTo bindTo}(receiver);
+MethodHandle mh0 = lookup().findVirtual(defc, name, type);
+MethodHandle mh1 = mh0.bindTo(receiver);
MethodType mt1 = mh1.type();
if (mh0.isVarargsCollector())
mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
return mh1;
- *
+ * }
* where {@code defc} is either {@code receiver.getClass()} or a super
* type of that class, in which the requested method is accessible
* to the lookup class.
@@ -1034,6 +1124,8 @@
* @exception SecurityException if a security manager is present and it
* refuses access
* @throws NullPointerException if any argument is null
+ * @see MethodHandle#bindTo
+ * @see #findVirtual
*/
public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
Class extends Object> refc = receiver.getClass(); // may get NPE
@@ -1043,7 +1135,8 @@
}
/**
- * Makes a direct method handle to m, if the lookup class has permission.
+ * Makes a direct method handle
+ * to m, if the lookup class has permission.
* If m is non-static, the receiver argument is treated as an initial argument.
* If m is virtual, overriding is respected on every call.
* Unlike the Core Reflection API, exceptions are not wrapped.
@@ -1090,13 +1183,21 @@
/**
* Produces a method handle for a reflected method.
* It will bypass checks for overriding methods on the receiver,
- * as if by a {@code invokespecial} instruction from within the {@code specialCaller}.
+ * as if called from an {@code invokespecial}
+ * instruction from within the explicitly specified {@code specialCaller}.
* The type of the method handle will be that of the method,
- * with the special caller type prepended (and not 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,
* access checking is performed immediately on behalf of the lookup class,
* as if {@code invokespecial} instruction were being linked.
*
+ * Before method resolution,
+ * 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.
+ *
* The returned method handle will have
* {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
* the method's variable arity modifier bit ({@code 0x0080}) is set.
@@ -1141,8 +1242,7 @@
* is set and {@code asVarargsCollector} fails
* @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);
assert(ctor.isConstructor());
Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
@@ -1202,7 +1302,8 @@
}
/**
- * Cracks a direct method handle created by this lookup object or a similar one.
+ * Cracks a direct method handle
+ * created by this lookup object or a similar one.
* Security and access checks are performed to ensure that this lookup object
* is capable of reproducing the target method handle.
* This means that the cracking may fail if target is a direct method handle
@@ -1215,6 +1316,7 @@
* refuses access
* @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails
* @exception NullPointerException if the target is {@code null}
+ * @see MethodHandleInfo
* @since 1.8
*/
public MethodHandleInfo revealDirect(MethodHandle target) {
@@ -1282,7 +1384,7 @@
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 "<" character. */
void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
if (name.startsWith("<") && refKind != REF_newInvokeSpecial)
throw new NoSuchMethodException("illegal method name: "+name);
@@ -1730,13 +1832,12 @@
* an {@link IllegalArgumentException} instead of invoking the target.
*
* This method is equivalent to the following code (though it may be more efficient):
- *
+ * {@code
MethodHandle invoker = MethodHandles.invoker(type);
int spreadArgCount = type.parameterCount() - leadingArgCount;
invoker = invoker.asSpreader(Object[].class, spreadArgCount);
return invoker;
- *
- *
+ * }
* This method throws no reflective or security exceptions.
* @param type the desired target type
* @param leadingArgCount number of fixed arguments, to be passed unchanged to the target
@@ -1762,9 +1863,7 @@
* an additional leading argument of type {@code MethodHandle}.
*
* This method is equivalent to the following code (though it may be more efficient):
- *
-publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
- *
+ * {@code publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)}
*
*
* Discussion:
@@ -1779,7 +1878,7 @@
* 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}
* method handle values, as long as they are compatible with the type of {@code X}.
- *
+ *
* (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}
* on the declared {@code invokeExact} or {@code invoke} method will raise an
@@ -1810,15 +1909,19 @@
* 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}.
*
- * 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)}
+ *
+ * Discussion:
+ * A {@linkplain MethodType#genericMethodType general method type} is one which
* mentions only {@code Object} arguments and return values.
* An invoker for such a type is capable of calling any method handle
* of the same arity as the general type.
- *
- * This method is equivalent to the following code (though it may be more efficient):
- *
-publicLookup().findVirtual(MethodHandle.class, "invoke", type)
- *
+ *
+ * (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}
+ * on the declared {@code invokeExact} or {@code invoke} method will raise an
+ * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)
*
* This method throws no reflective or security exceptions.
* @param type the desired target type
@@ -2105,7 +2208,7 @@
* they will come after.
*
* Example:
- *
+ * {@code
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
@@ -2116,11 +2219,11 @@
MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
assertEquals(bigType, d0.type());
assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
- *
+ * }
*
* This method is also equivalent to the following code:
*
- * {@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]))}
*
* @param target the method handle to invoke after the arguments are dropped
* @param valueTypes the type(s) of the argument(s) to drop
@@ -2163,7 +2266,7 @@
* they will come after.
*
* Example:
- *
+ * {@code
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
@@ -2178,11 +2281,11 @@
assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
- *
+ * }
*
* This method is also equivalent to the following code:
*
- * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
+ * {@link #dropArguments(MethodHandle,int,List) dropArguments}{@code (target, pos, Arrays.asList(valueTypes))}
*
* @param target the method handle to invoke after the arguments are dropped
* @param valueTypes the type(s) of the argument(s) to drop
@@ -2228,8 +2331,8 @@
* It is an error if there are elements of {@code filters}
* (null or not)
* which do not correspond to argument positions in the target.
- * Example:
- *
+ * Example:
+ *
{@code
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
@@ -2244,15 +2347,15 @@
assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
- *
+ * }
* Here is pseudocode for the resulting adapter:
- *
+ * {@code
* V target(P... p, A[i]... a[i], B... b);
* A[i] filter[i](V[i]);
* T adapter(P... p, V[i]... v[i], B... b) {
* return target(p..., f[i](v[i])..., b...);
* }
- *
+ * }
*
* @param target the method handle to invoke after arguments are filtered
* @param pos the position of the first argument to filter
@@ -2322,7 +2425,7 @@
* 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.
* Example:
- *
+ * {@code
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
@@ -2347,9 +2450,9 @@
MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
assertEquals("[top, [[up, down, strange], charm], bottom]",
(String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
- *
+ * }
* Here is pseudocode for the resulting adapter:
- *
+ * {@code
* T target(A...,V,C...);
* V filter(B...);
* T adapter(A... a,B... b,C... c) {
@@ -2370,7 +2473,7 @@
* filter3(b...);
* return target3(a...,c...);
* }
- *
+ * }
*
* A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to
* one which first "folds" the affected arguments, and then drops them, in separate
@@ -2426,8 +2529,8 @@
* in the resulting adapted method handle.
* The argument type of the filter (if any) must be identical to the
* return type of the target.
- * Example:
- *
+ * Example:
+ *
{@code
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
@@ -2438,9 +2541,9 @@
System.out.println((String) cat.invokeExact("x", "y")); // xy
MethodHandle f0 = filterReturnValue(cat, length);
System.out.println((int) f0.invokeExact("x", "y")); // 2
- *
+ * }
* Here is pseudocode for the resulting adapter:
- *
+ * {@code
* V target(A...);
* T filter(V);
* T adapter(A... a) {
@@ -2461,7 +2564,7 @@
* V v = target3(a...);
* filter3(v);
* }
- *
+ * }
* @param target the method handle to invoke before filtering the return value
* @param filter method handle to call on the return value
* @return method handle which incorporates the specified return value filtering logic
@@ -2517,8 +2620,8 @@
* consider using {@link MethodHandle#asCollector asCollector} instead, since those
* arguments will not need to be live on the stack on entry to the
* target.)
- * Example:
- *
+ * Example:
+ *
{@code
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
@@ -2531,9 +2634,9 @@
MethodHandle catTrace = foldArguments(cat, trace);
// also prints "boo":
assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
- *
+ * }
* Here is pseudocode for the resulting adapter:
- *
+ * {@code
* // there are N arguments in A...
* T target(V, A[N]..., B...);
* V combiner(A...);
@@ -2548,7 +2651,7 @@
* combiner2(a...);
* return target2(a..., b...);
* }
- *
+ * }
* @param target the method handle to invoke after arguments are combined
* @param combiner method handle to call initially on the incoming arguments
* @return method handle which incorporates the specified argument folding logic
@@ -2591,7 +2694,7 @@
* of the test must be boolean, and the test is allowed
* to have fewer arguments than the other two method handles.
* Here is pseudocode for the resulting adapter:
- *
+ * {@code
* boolean test(A...);
* T target(A...,B...);
* T fallback(A...,B...);
@@ -2601,7 +2704,7 @@
* else
* return fallback(a..., b...);
* }
- *
+ * }
* Note that the test arguments ({@code a...} in the pseudocode) cannot
* be modified by execution of the test, and so are passed unchanged
* from the caller to the target or fallback as appropriate.
@@ -2653,7 +2756,7 @@
* (similarly to the predicate in {@link #guardWithTest guardWithTest}).
* Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
* Here is pseudocode for the resulting adapter:
- *
+ * {@code
* T target(A..., B...);
* T handler(ExType, A...);
* T adapter(A... a, B... b) {
@@ -2663,7 +2766,7 @@
* return handler(ex, a...);
* }
* }
- *
+ * }
* Note that the saved arguments ({@code a...} in the pseudocode) cannot
* be modified by execution of the target, and so are passed unchanged
* from the caller to the handler, if the handler is invoked.
diff -r da86f7904e6d -r cc85c8626435 jdk/src/share/classes/java/lang/invoke/MethodType.java
--- a/jdk/src/share/classes/java/lang/invoke/MethodType.java Sat Oct 05 05:30:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodType.java Sat Oct 05 05:30:40 2013 -0700
@@ -77,7 +77,8 @@
* A method type may be loaded by an {@code ldc} instruction which refers
* to a suitable {@code CONSTANT_MethodType} constant pool entry.
* The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
- * For more details, see the package summary.
+ * (For full details on method type constants,
+ * see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
*
* When the JVM materializes a {@code MethodType} from a descriptor string,
* all classes named in the descriptor must be accessible, and will be loaded.
@@ -940,10 +941,10 @@
* Instead, the return type and parameter type arrays are written directly
* from the {@code writeObject} method, using two calls to {@code s.writeObject}
* as follows:
- *
+ * {@code
s.writeObject(this.returnType());
s.writeObject(this.parameterArray());
- *
+ * }
*
* The deserialized field values are checked as if they were
* provided to the factory method {@link #methodType(Class,Class[]) methodType}.
diff -r da86f7904e6d -r cc85c8626435 jdk/src/share/classes/java/lang/invoke/MutableCallSite.java
--- a/jdk/src/share/classes/java/lang/invoke/MutableCallSite.java Sat Oct 05 05:30:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MutableCallSite.java Sat Oct 05 05:30:40 2013 -0700
@@ -38,7 +38,7 @@
* Here is an example of a mutable call site which introduces a
* state variable into a method handle chain.
*
- *
+ * {@code
MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
MethodHandle MH_name = name.dynamicInvoker();
MethodType MT_str1 = MethodType.methodType(String.class);
@@ -50,10 +50,10 @@
name.setTarget(MethodHandles.constant(String.class, "Fred"));
assertEquals("FRED", (String) worker1.invokeExact());
// (mutation can be continued indefinitely)
- *
+ * }
*
* The same call site may be used in several places at once.
- *
+ * {@code
MethodType MT_str2 = MethodType.methodType(String.class, String.class);
MethodHandle MH_cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
@@ -63,7 +63,7 @@
name.setTarget(MethodHandles.constant(String.class, "Wilma"));
assertEquals("WILMA", (String) worker1.invokeExact());
assertEquals("Wilma, dear?", (String) worker2.invokeExact());
- *
+ * }
*
* Non-synchronization of target values:
* A write to a mutable call site's target does not force other threads
diff -r da86f7904e6d -r cc85c8626435 jdk/src/share/classes/java/lang/invoke/SwitchPoint.java
--- a/jdk/src/share/classes/java/lang/invoke/SwitchPoint.java Sat Oct 05 05:30:39 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/SwitchPoint.java Sat Oct 05 05:30:40 2013 -0700
@@ -55,7 +55,7 @@
* At that point {@code guardWithTest} may ignore {@code T} and return {@code F}.
*
* Here is an example of a switch point in action:
- *
+ * {@code
MethodHandle MH_strcat = MethodHandles.lookup()
.findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class));
SwitchPoint spt = new SwitchPoint();
@@ -68,7 +68,7 @@
SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
assert(spt.hasBeenInvalidated());
assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
- *
+ * }
*
* Discussion:
* Switch points are useful without subclassing. They may also be subclassed.
@@ -82,7 +82,7 @@
* Implementation Note:
* A switch point behaves as if implemented on top of {@link MutableCallSite},
* approximately as follows:
- *
+ * {@code
public class SwitchPoint {
private static final MethodHandle
K_true = MethodHandles.constant(boolean.class, true),
@@ -106,7 +106,7 @@
MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
}
}
- *
+ * }
* @author Remi Forax, JSR 292 EG
*/
public class SwitchPoint {
diff -r da86f7904e6d -r cc85c8626435 jdk/src/share/classes/sun/invoke/WrapperInstance.java
--- a/jdk/src/share/classes/sun/invoke/WrapperInstance.java Sat Oct 05 05:30:39 2013 -0700
+++ b/jdk/src/share/classes/sun/invoke/WrapperInstance.java Sat Oct 05 05:30:40 2013 -0700
@@ -30,7 +30,7 @@
/**
* Private API used inside of java.lang.invoke.MethodHandles.
* 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
* to {@code asInstance}.
* This allows applications to repeatedly convert between method handles
diff -r da86f7904e6d -r cc85c8626435 jdk/src/share/classes/sun/invoke/util/VerifyAccess.java
--- a/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java Sat Oct 05 05:30:39 2013 -0700
+++ b/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java Sat Oct 05 05:30:40 2013 -0700
@@ -172,7 +172,7 @@
* Decide if the given method type, attributed to a member or symbolic
* 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 refc
+ * @param refc the class attempting to make the reference
*/
public static boolean isTypeVisible(Class> type, Class> refc) {
if (type == refc) return true; // easy check
@@ -197,7 +197,7 @@
* Decide if the given method type, attributed to a member or symbolic
* 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 refc
+ * @param refc the class attempting to make the reference
*/
public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class> refc) {
for (int n = -1, max = type.parameterCount(); n < max; n++) {
@@ -210,8 +210,8 @@
/**
* Test if two classes have the same class loader and package qualifier.
- * @param class1
- * @param class2
+ * @param class1 a class
+ * @param class2 another class
* @return whether they are in the same package
*/
public static boolean isSamePackage(Class> class1, Class> class2) {
@@ -244,8 +244,8 @@
/**
* 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.
- * @param class1
- * @param class2
+ * @param class1 a class
+ * @param class2 another class
* @return whether they are identical or nested together
*/
public static boolean isSamePackageMember(Class> class1, Class> class2) {
@@ -287,8 +287,8 @@
/**
* Is the class loader of parentClass identical to, or an ancestor of,
* the class loader of childClass?
- * @param parentClass
- * @param childClass
+ * @param parentClass a class
+ * @param childClass another class, which may be a descendent of the first class
* @return whether parentClass precedes or equals childClass in class loader order
*/
public static boolean classLoaderIsAncestor(Class> parentClass, Class> childClass) {
diff -r da86f7904e6d -r cc85c8626435 jdk/src/share/classes/sun/invoke/util/VerifyType.java
--- a/jdk/src/share/classes/sun/invoke/util/VerifyType.java Sat Oct 05 05:30:39 2013 -0700
+++ b/jdk/src/share/classes/sun/invoke/util/VerifyType.java Sat Oct 05 05:30:40 2013 -0700
@@ -41,8 +41,8 @@
* True if a value can be stacked as the source type and unstacked as the
* destination type, without violating the JVM's type consistency.
*
- * @param call the type of a stacked value
- * @param recv the type by which we'd like to treat it
+ * @param src the type of a stacked value
+ * @param dst the type by which we'd like to treat it
* @return whether the retyping can be done without motion or reformatting
*/
public static boolean isNullConversion(Class> src, Class> dst) {
@@ -67,9 +67,8 @@
/**
* Specialization of isNullConversion to reference types.
-
- * @param call the type of a stacked value
- * @param recv the reference type by which we'd like to treat it
+ * @param src the type of a stacked value
+ * @param dst the reference type by which we'd like to treat it
* @return whether the retyping can be done without a cast
*/
public static boolean isNullReferenceConversion(Class> src, Class> dst) {
diff -r da86f7904e6d -r cc85c8626435 jdk/test/java/lang/invoke/AccessControlTest.java
--- a/jdk/test/java/lang/invoke/AccessControlTest.java Sat Oct 05 05:30:39 2013 -0700
+++ b/jdk/test/java/lang/invoke/AccessControlTest.java Sat Oct 05 05:30:40 2013 -0700
@@ -133,7 +133,7 @@
}
/** Simulate all assertions from the spec. for Lookup.in:
- *
+ *
* Creates a lookup on the specified new lookup class.
* [A1] The resulting object will report the specified
* class as its own {@link #lookupClass lookupClass}.
@@ -155,7 +155,7 @@
*
* Other than the above cases, the new lookup will have the same
* access capabilities as the original. [A8]
- *
+ *
*/
public LookupCase in(Class> c2) {
Class> c1 = lookupClass();
diff -r da86f7904e6d -r cc85c8626435 jdk/test/java/lang/invoke/MethodHandlesTest.java
--- a/jdk/test/java/lang/invoke/MethodHandlesTest.java Sat Oct 05 05:30:39 2013 -0700
+++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java Sat Oct 05 05:30:40 2013 -0700
@@ -496,7 +496,7 @@
return lookup.in(defc);
}
- /** Is findVirtual (etc.) of "" supposed to elicit a NoSuchMethodException? */
+ /** Is findVirtual (etc.) of "<init<" supposed to elicit a NoSuchMethodException? */
final static boolean INIT_REF_CAUSES_NSME = true;
@Test
diff -r da86f7904e6d -r cc85c8626435 jdk/test/java/lang/invoke/RevealDirectTest.java
--- a/jdk/test/java/lang/invoke/RevealDirectTest.java Sat Oct 05 05:30:39 2013 -0700
+++ b/jdk/test/java/lang/invoke/RevealDirectTest.java Sat Oct 05 05:30:40 2013 -0700
@@ -104,6 +104,9 @@
private static Lookup localLookup() { return lookup(); }
private static List members() { return getMembers(lookup().lookupClass()); };
}
+ static class Nestmate {
+ private static Lookup localLookup() { return lookup(); }
+ }
static boolean VERBOSE = false;
@@ -152,7 +155,10 @@
getMembers(Method.class, "invoke"));
mems = callerSensitive(true, publicOnly(mems));
// 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 {
if (VERBOSE) System.out.println("@Test testMethodHandleNatives");
@@ -703,7 +709,7 @@
try {
info = revLookup.revealDirect(mh);
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 (expectEx2)
continue; // this is OK; we expected the reflect to fail