< prev index next >
src/java.base/share/classes/java/lang/invoke/MethodHandles.java
Print this page
rev 50604 : imported patch jep181-rev1
*** 467,485 ****
* with special names ({@code "<init>"} and {@code "<clinit>"}).
* The internal syntax of invocation instructions allows them to refer to such internal
* methods as if they were normal methods, but the JVM bytecode verifier rejects them.
* A lookup of such an internal method will produce a {@code NoSuchMethodException}.
* <p>
! * In some cases, access between nested classes is obtained by the Java compiler by creating
! * an wrapper method to access a private method of another class
! * in the same top-level declaration.
* For example, a nested class {@code C.D}
* can access private members within other related classes such as
* {@code C}, {@code C.D.E}, or {@code C.B},
* but the Java compiler may need to generate wrapper methods in
* those related classes. In such cases, a {@code Lookup} object on
! * {@code C.E} would be unable to those private members.
* A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
* which can transform a lookup on {@code C.E} into one on any of those other
* classes, without special elevation of privilege.
* <p>
* The accesses permitted to a given lookup object may be limited,
--- 467,490 ----
* with special names ({@code "<init>"} and {@code "<clinit>"}).
* The internal syntax of invocation instructions allows them to refer to such internal
* methods as if they were normal methods, but the JVM bytecode verifier rejects them.
* A lookup of such an internal method will produce a {@code NoSuchMethodException}.
* <p>
! * If the relationship between nested types is expressed directly through the
! * {@code NestHost} and {@code NestMembers} attributes
! * (see the Java Virtual Machine Specification, sections 4.7.28 and 4.7.29),
! * then the associated {@code Lookup} object provides direct access to
! * the lookup class and all of its nestmates
! * (see {@link java.lang.Class#getNestHost Class.getNestHost}).
! * Otherwise, access between nested classes is obtained by the Java compiler creating
! * a wrapper method to access a private method of another class in the same nest.
* For example, a nested class {@code C.D}
* can access private members within other related classes such as
* {@code C}, {@code C.D.E}, or {@code C.B},
* but the Java compiler may need to generate wrapper methods in
* those related classes. In such cases, a {@code Lookup} object on
! * {@code C.E} would be unable to access those private members.
* A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
* which can transform a lookup on {@code C.E} into one on any of those other
* classes, without special elevation of privilege.
* <p>
* The accesses permitted to a given lookup object may be limited,
*** 497,511 ****
* <p style="font-size:smaller;">
* <a id="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
--- 502,517 ----
* <p style="font-size:smaller;">
* <a id="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
! * (which includes the private members of nestmates).
* 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 and its nestmates
* <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
*** 726,738 ****
* {@linkplain #MODULE MODULE (0x10)},
* and {@linkplain #UNCONDITIONAL UNCONDITIONAL (0x20)}.
* <p>
* A freshly-created lookup object
* on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has
! * all possible bits set, except {@code UNCONDITIONAL}. The lookup can be used to
! * access all members of the caller's class, all public types in the caller's module,
! * and all public types in packages exported by other modules to the caller's module.
* A lookup object on a new lookup class
* {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
* may have some mode bits set to zero.
* Mode bits can also be
* {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}.
--- 732,742 ----
* {@linkplain #MODULE MODULE (0x10)},
* and {@linkplain #UNCONDITIONAL UNCONDITIONAL (0x20)}.
* <p>
* A freshly-created lookup object
* on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has
! * all possible bits set, except {@code UNCONDITIONAL}.
* A lookup object on a new lookup class
* {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
* may have some mode bits set to zero.
* Mode bits can also be
* {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}.
*** 1104,1115 ****
* 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 object.
* <p>
* When called, the handle will treat the first argument as a receiver
! * and dispatch on the receiver's type to determine which method
* implementation to enter.
* (The dispatching action is identical with that performed by an
* {@code invokevirtual} or {@code invokeinterface} instruction.)
* <p>
* The first argument will be of type {@code refc} if the lookup
* class has full privileges to access the member. Otherwise
--- 1108,1120 ----
* 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 object.
* <p>
* When called, the handle will treat the first argument as a receiver
! * and, for non-private methods, dispatch on the receiver's type to determine which method
* implementation to enter.
+ * For private methods the named method in {@code refc} will be invoked on the receiver.
* (The dispatching action is identical with that performed by an
* {@code invokevirtual} or {@code invokeinterface} instruction.)
* <p>
* The first argument will be of type {@code refc} if the lookup
* class has full privileges to access the member. Otherwise
*** 1169,1179 ****
* @param type the type of the method, with the receiver argument omitted
* @return the desired method handle
* @throws NoSuchMethodException if the method does not exist
* @throws IllegalAccessException if access checking fails,
* or if the method is {@code static},
- * or if the method is {@code private} method of interface,
* or if the method's variable arity modifier bit
* is set and {@code asVarargsCollector} fails
* @exception SecurityException if a security manager is present and it
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
--- 1174,1183 ----
*** 2223,2256 ****
if (Modifier.isProtected(mods))
return "member is protected";
return "member is private to package";
}
- private static final boolean ALLOW_NESTMATE_ACCESS = false;
-
private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
int allowedModes = this.allowedModes;
if (allowedModes == TRUSTED) return;
if (!hasPrivateAccess()
|| (specialCaller != lookupClass()
// ensure non-abstract methods in superinterfaces can be special-invoked
! && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))
! && !(ALLOW_NESTMATE_ACCESS &&
! VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
throw new MemberName(specialCaller).
makeAccessException("no private access for invokespecial", this);
}
private boolean restrictProtectedReceiver(MemberName method) {
// The accessing class only has the right to use a protected member
// on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc.
if (!method.isProtected() || method.isStatic()
|| allowedModes == TRUSTED
|| method.getDeclaringClass() == lookupClass()
! || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
! || (ALLOW_NESTMATE_ACCESS &&
! VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
return false;
return true;
}
private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
assert(!method.isStatic());
--- 2227,2254 ----
if (Modifier.isProtected(mods))
return "member is protected";
return "member is private to package";
}
private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
int allowedModes = this.allowedModes;
if (allowedModes == TRUSTED) return;
if (!hasPrivateAccess()
|| (specialCaller != lookupClass()
// ensure non-abstract methods in superinterfaces can be special-invoked
! && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))))
throw new MemberName(specialCaller).
makeAccessException("no private access for invokespecial", this);
}
private boolean restrictProtectedReceiver(MemberName method) {
// The accessing class only has the right to use a protected member
// on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc.
if (!method.isProtected() || method.isStatic()
|| allowedModes == TRUSTED
|| method.getDeclaringClass() == lookupClass()
! || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass()))
return false;
return true;
}
private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
assert(!method.isStatic());
*** 2286,2295 ****
--- 2284,2294 ----
}
/** Common code for all methods; do not call directly except from immediately above. */
private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
boolean checkSecurity,
boolean doRestrict, Class<?> boundCallerClass) throws IllegalAccessException {
+
checkMethod(refKind, refc, method);
// Optionally check with the security manager; this isn't needed for unreflect* calls.
if (checkSecurity)
checkSecurityManager(refc, method);
assert(!method.isMethodHandleInvoke());
*** 2298,2307 ****
--- 2297,2307 ----
refc != lookupClass() &&
!refc.isInterface() &&
refc != lookupClass().getSuperclass() &&
refc.isAssignableFrom(lookupClass())) {
assert(!method.getName().equals("<init>")); // not this code path
+
// Per JVMS 6.5, desc. of invokespecial instruction:
// If the method is in a superclass of the LC,
// and if our original search was above LC.super,
// repeat the search (symbolic lookup) from LC.super
// and continue with the direct superclass of that class,
< prev index next >