< 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 >