< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodHandles.java

Print this page
rev 50604 : imported patch jep181-rev1


 452      * In addition, if the desired member is a non-static field or method
 453      * in a different package, the resulting method handle may only be applied
 454      * to objects of the lookup class or one of its subclasses.
 455      * This requirement is enforced by narrowing the type of the leading
 456      * {@code this} parameter from {@code C}
 457      * (which will necessarily be a superclass of the lookup class)
 458      * to the lookup class itself.
 459      * <p>
 460      * The JVM imposes a similar requirement on {@code invokespecial} instruction,
 461      * that the receiver argument must match both the resolved method <em>and</em>
 462      * the current class.  Again, this requirement is enforced by narrowing the
 463      * type of the leading parameter to the resulting method handle.
 464      * (See the Java Virtual Machine Specification, section 4.10.1.9.)
 465      * <p>
 466      * The JVM represents constructors and static initializer blocks as internal methods
 467      * with special names ({@code "<init>"} and {@code "<clinit>"}).
 468      * The internal syntax of invocation instructions allows them to refer to such internal
 469      * methods as if they were normal methods, but the JVM bytecode verifier rejects them.
 470      * A lookup of such an internal method will produce a {@code NoSuchMethodException}.
 471      * <p>
 472      * In some cases, access between nested classes is obtained by the Java compiler by creating
 473      * an wrapper method to access a private method of another class
 474      * in the same top-level declaration.





 475      * For example, a nested class {@code C.D}
 476      * can access private members within other related classes such as
 477      * {@code C}, {@code C.D.E}, or {@code C.B},
 478      * but the Java compiler may need to generate wrapper methods in
 479      * those related classes.  In such cases, a {@code Lookup} object on
 480      * {@code C.E} would be unable to those private members.
 481      * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
 482      * which can transform a lookup on {@code C.E} into one on any of those other
 483      * classes, without special elevation of privilege.
 484      * <p>
 485      * The accesses permitted to a given lookup object may be limited,
 486      * according to its set of {@link #lookupModes lookupModes},
 487      * to a subset of members normally accessible to the lookup class.
 488      * For example, the {@link MethodHandles#publicLookup publicLookup}
 489      * method produces a lookup object which is only allowed to access
 490      * public members in public classes of exported packages.
 491      * The caller sensitive method {@link MethodHandles#lookup lookup}
 492      * produces a lookup object with full capabilities relative to
 493      * its caller class, to emulate all supported bytecode behaviors.
 494      * Also, the {@link Lookup#in Lookup.in} method may produce a lookup object
 495      * with fewer access modes than the original lookup object.
 496      *
 497      * <p style="font-size:smaller;">
 498      * <a id="privacc"></a>
 499      * <em>Discussion of private access:</em>
 500      * We say that a lookup has <em>private access</em>
 501      * if its {@linkplain #lookupModes lookup modes}
 502      * include the possibility of accessing {@code private} members.

 503      * As documented in the relevant methods elsewhere,
 504      * only lookups with private access possess the following capabilities:
 505      * <ul style="font-size:smaller;">
 506      * <li>access private fields, methods, and constructors of the lookup class
 507      * <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods,
 508      *     such as {@code Class.forName}
 509      * <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
 510      * <li>avoid <a href="MethodHandles.Lookup.html#secmgr">package access checks</a>
 511      *     for classes accessible to the lookup class
 512      * <li>create {@link Lookup#in delegated lookup objects} which have private access to other classes
 513      *     within the same package member
 514      * </ul>
 515      * <p style="font-size:smaller;">
 516      * Each of these permissions is a consequence of the fact that a lookup object
 517      * with private access can be securely traced back to an originating class,
 518      * whose <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> and Java language access permissions
 519      * can be reliably determined and emulated by method handles.
 520      *
 521      * <h1><a id="secmgr"></a>Security manager interactions</h1>
 522      * Although bytecode instructions can only refer to classes in
 523      * a related class loader, this API can search for methods in any
 524      * class, as long as a reference to its {@code Class} object is
 525      * available.  Such cross-loader references are also possible with the
 526      * Core Reflection API, and are impossible to bytecode instructions


 711         public Class<?> lookupClass() {
 712             return lookupClass;
 713         }
 714 
 715         // This is just for calling out to MethodHandleImpl.
 716         private Class<?> lookupClassOrNull() {
 717             return (allowedModes == TRUSTED) ? null : lookupClass;
 718         }
 719 
 720         /** Tells which access-protection classes of members this lookup object can produce.
 721          *  The result is a bit-mask of the bits
 722          *  {@linkplain #PUBLIC PUBLIC (0x01)},
 723          *  {@linkplain #PRIVATE PRIVATE (0x02)},
 724          *  {@linkplain #PROTECTED PROTECTED (0x04)},
 725          *  {@linkplain #PACKAGE PACKAGE (0x08)},
 726          *  {@linkplain #MODULE MODULE (0x10)},
 727          *  and {@linkplain #UNCONDITIONAL UNCONDITIONAL (0x20)}.
 728          *  <p>
 729          *  A freshly-created lookup object
 730          *  on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has
 731          *  all possible bits set, except {@code UNCONDITIONAL}. The lookup can be used to
 732          *  access all members of the caller's class, all public types in the caller's module,
 733          *  and all public types in packages exported by other modules to the caller's module.
 734          *  A lookup object on a new lookup class
 735          *  {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
 736          *  may have some mode bits set to zero.
 737          *  Mode bits can also be
 738          *  {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}.
 739          *  Once cleared, mode bits cannot be restored from the downgraded lookup object.
 740          *  The purpose of this is to restrict access via the new lookup object,
 741          *  so that it can access only names which can be reached by the original
 742          *  lookup object, and also by the new lookup class.
 743          *  @return the lookup modes, which limit the kinds of access performed by this lookup object
 744          *  @see #in
 745          *  @see #dropLookupMode
 746          *
 747          *  @revised 9
 748          *  @spec JPMS
 749          */
 750         public int lookupModes() {
 751             return allowedModes & ALL_MODES;
 752         }
 753 


1089          *                                or if the method is not {@code static},
1090          *                                or if the method's variable arity modifier bit
1091          *                                is set and {@code asVarargsCollector} fails
1092          * @exception SecurityException if a security manager is present and it
1093          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1094          * @throws NullPointerException if any argument is null
1095          */
1096         public
1097         MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
1098             MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);
1099             return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerClass(method));
1100         }
1101 
1102         /**
1103          * Produces a method handle for a virtual method.
1104          * The type of the method handle will be that of the method,
1105          * with the receiver type (usually {@code refc}) prepended.
1106          * The method and all its argument types must be accessible to the lookup object.
1107          * <p>
1108          * When called, the handle will treat the first argument as a receiver
1109          * and dispatch on the receiver's type to determine which method
1110          * implementation to enter.

1111          * (The dispatching action is identical with that performed by an
1112          * {@code invokevirtual} or {@code invokeinterface} instruction.)
1113          * <p>
1114          * The first argument will be of type {@code refc} if the lookup
1115          * class has full privileges to access the member.  Otherwise
1116          * the member must be {@code protected} and the first argument
1117          * will be restricted in type to the lookup class.
1118          * <p>
1119          * The returned method handle will have
1120          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
1121          * the method's variable arity modifier bit ({@code 0x0080}) is set.
1122          * <p>
1123          * Because of the general <a href="MethodHandles.Lookup.html#equiv">equivalence</a> between {@code invokevirtual}
1124          * instructions and method handles produced by {@code findVirtual},
1125          * if the class is {@code MethodHandle} and the name string is
1126          * {@code invokeExact} or {@code invoke}, the resulting
1127          * method handle is equivalent to one produced by
1128          * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
1129          * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
1130          * with the same {@code type} argument.


1154 MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class,
1155   "subSequence", methodType(CharSequence.class, int.class, int.class));
1156 assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString());
1157 // constructor "internal method" must be accessed differently:
1158 MethodType MT_newString = methodType(void.class); //()V for new String()
1159 try { assertEquals("impossible", lookup()
1160         .findVirtual(String.class, "<init>", MT_newString));
1161  } catch (NoSuchMethodException ex) { } // OK
1162 MethodHandle MH_newString = publicLookup()
1163   .findConstructor(String.class, MT_newString);
1164 assertEquals("", (String) MH_newString.invokeExact());
1165          * }</pre></blockquote>
1166          *
1167          * @param refc the class or interface from which the method is accessed
1168          * @param name the name of the method
1169          * @param type the type of the method, with the receiver argument omitted
1170          * @return the desired method handle
1171          * @throws NoSuchMethodException if the method does not exist
1172          * @throws IllegalAccessException if access checking fails,
1173          *                                or if the method is {@code static},
1174          *                                or if the method is {@code private} method of interface,
1175          *                                or if the method's variable arity modifier bit
1176          *                                is set and {@code asVarargsCollector} fails
1177          * @exception SecurityException if a security manager is present and it
1178          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1179          * @throws NullPointerException if any argument is null
1180          */
1181         public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
1182             if (refc == MethodHandle.class) {
1183                 MethodHandle mh = findVirtualForMH(name, type);
1184                 if (mh != null)  return mh;
1185             } else if (refc == VarHandle.class) {
1186                 MethodHandle mh = findVirtualForVH(name, type);
1187                 if (mh != null)  return mh;
1188             }
1189             byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
1190             MemberName method = resolveOrFail(refKind, refc, name, type);
1191             return getDirectMethod(refKind, refc, method, findBoundCallerClass(method));
1192         }
1193         private MethodHandle findVirtualForMH(String name, MethodType type) {
1194             // these names require special lookups because of the implicit MethodType argument


2208             // check the class first:
2209             boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
2210                                (defc == refc ||
2211                                 Modifier.isPublic(refc.getModifiers())));
2212             if (!classOK && (allowedModes & PACKAGE) != 0) {
2213                 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), FULL_POWER_MODES) &&
2214                            (defc == refc ||
2215                             VerifyAccess.isClassAccessible(refc, lookupClass(), FULL_POWER_MODES)));
2216             }
2217             if (!classOK)
2218                 return "class is not public";
2219             if (Modifier.isPublic(mods))
2220                 return "access to public member failed";  // (how?, module not readable?)
2221             if (Modifier.isPrivate(mods))
2222                 return "member is private";
2223             if (Modifier.isProtected(mods))
2224                 return "member is protected";
2225             return "member is private to package";
2226         }
2227 
2228         private static final boolean ALLOW_NESTMATE_ACCESS = false;
2229 
2230         private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
2231             int allowedModes = this.allowedModes;
2232             if (allowedModes == TRUSTED)  return;
2233             if (!hasPrivateAccess()
2234                 || (specialCaller != lookupClass()
2235                        // ensure non-abstract methods in superinterfaces can be special-invoked
2236                     && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))
2237                     && !(ALLOW_NESTMATE_ACCESS &&
2238                          VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
2239                 throw new MemberName(specialCaller).
2240                     makeAccessException("no private access for invokespecial", this);
2241         }
2242 
2243         private boolean restrictProtectedReceiver(MemberName method) {
2244             // The accessing class only has the right to use a protected member
2245             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
2246             if (!method.isProtected() || method.isStatic()
2247                 || allowedModes == TRUSTED
2248                 || method.getDeclaringClass() == lookupClass()
2249                 || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
2250                 || (ALLOW_NESTMATE_ACCESS &&
2251                     VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
2252                 return false;
2253             return true;
2254         }
2255         private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
2256             assert(!method.isStatic());
2257             // receiver type of mh is too wide; narrow to caller
2258             if (!method.getDeclaringClass().isAssignableFrom(caller)) {
2259                 throw method.makeAccessException("caller class must be a subclass below the method", caller);
2260             }
2261             MethodType rawType = mh.type();
2262             if (caller.isAssignableFrom(rawType.parameterType(0))) return mh; // no need to restrict; already narrow
2263             MethodType narrowType = rawType.changeParameterType(0, caller);
2264             assert(!mh.isVarargsCollector());  // viewAsType will lose varargs-ness
2265             assert(mh.viewAsTypeChecks(narrowType, true));
2266             return mh.copyWith(narrowType, mh.form);
2267         }
2268 
2269         /** Check access and get the requested method. */
2270         private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> boundCallerClass) throws IllegalAccessException {
2271             final boolean doRestrict    = true;
2272             final boolean checkSecurity = true;
2273             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, boundCallerClass);
2274         }
2275         /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */
2276         private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class<?> refc, MemberName method, Class<?> boundCallerClass) throws IllegalAccessException {
2277             final boolean doRestrict    = false;
2278             final boolean checkSecurity = true;
2279             return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, boundCallerClass);
2280         }
2281         /** Check access and get the requested method, eliding security manager checks. */
2282         private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> boundCallerClass) throws IllegalAccessException {
2283             final boolean doRestrict    = true;
2284             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
2285             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, boundCallerClass);
2286         }
2287         /** Common code for all methods; do not call directly except from immediately above. */
2288         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
2289                                                    boolean checkSecurity,
2290                                                    boolean doRestrict, Class<?> boundCallerClass) throws IllegalAccessException {

2291             checkMethod(refKind, refc, method);
2292             // Optionally check with the security manager; this isn't needed for unreflect* calls.
2293             if (checkSecurity)
2294                 checkSecurityManager(refc, method);
2295             assert(!method.isMethodHandleInvoke());
2296 
2297             if (refKind == REF_invokeSpecial &&
2298                 refc != lookupClass() &&
2299                 !refc.isInterface() &&
2300                 refc != lookupClass().getSuperclass() &&
2301                 refc.isAssignableFrom(lookupClass())) {
2302                 assert(!method.getName().equals("<init>"));  // not this code path

2303                 // Per JVMS 6.5, desc. of invokespecial instruction:
2304                 // If the method is in a superclass of the LC,
2305                 // and if our original search was above LC.super,
2306                 // repeat the search (symbolic lookup) from LC.super
2307                 // and continue with the direct superclass of that class,
2308                 // and so forth, until a match is found or no further superclasses exist.
2309                 // FIXME: MemberName.resolve should handle this instead.
2310                 Class<?> refcAsSuper = lookupClass();
2311                 MemberName m2;
2312                 do {
2313                     refcAsSuper = refcAsSuper.getSuperclass();
2314                     m2 = new MemberName(refcAsSuper,
2315                                         method.getName(),
2316                                         method.getMethodType(),
2317                                         REF_invokeSpecial);
2318                     m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
2319                 } while (m2 == null &&         // no method is found yet
2320                          refc != refcAsSuper); // search up to refc
2321                 if (m2 == null)  throw new InternalError(method.toString());
2322                 method = m2;




 452      * In addition, if the desired member is a non-static field or method
 453      * in a different package, the resulting method handle may only be applied
 454      * to objects of the lookup class or one of its subclasses.
 455      * This requirement is enforced by narrowing the type of the leading
 456      * {@code this} parameter from {@code C}
 457      * (which will necessarily be a superclass of the lookup class)
 458      * to the lookup class itself.
 459      * <p>
 460      * The JVM imposes a similar requirement on {@code invokespecial} instruction,
 461      * that the receiver argument must match both the resolved method <em>and</em>
 462      * the current class.  Again, this requirement is enforced by narrowing the
 463      * type of the leading parameter to the resulting method handle.
 464      * (See the Java Virtual Machine Specification, section 4.10.1.9.)
 465      * <p>
 466      * The JVM represents constructors and static initializer blocks as internal methods
 467      * with special names ({@code "<init>"} and {@code "<clinit>"}).
 468      * The internal syntax of invocation instructions allows them to refer to such internal
 469      * methods as if they were normal methods, but the JVM bytecode verifier rejects them.
 470      * A lookup of such an internal method will produce a {@code NoSuchMethodException}.
 471      * <p>
 472      * If the relationship between nested types is expressed directly through the
 473      * {@code NestHost} and {@code NestMembers} attributes
 474      * (see the Java Virtual Machine Specification, sections 4.7.28 and 4.7.29),
 475      * then the associated {@code Lookup} object provides direct access to
 476      * the lookup class and all of its nestmates
 477      * (see {@link java.lang.Class#getNestHost Class.getNestHost}).
 478      * Otherwise, access between nested classes is obtained by the Java compiler creating
 479      * a wrapper method to access a private method of another class in the same nest.
 480      * For example, a nested class {@code C.D}
 481      * can access private members within other related classes such as
 482      * {@code C}, {@code C.D.E}, or {@code C.B},
 483      * but the Java compiler may need to generate wrapper methods in
 484      * those related classes.  In such cases, a {@code Lookup} object on
 485      * {@code C.E} would be unable to access those private members.
 486      * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
 487      * which can transform a lookup on {@code C.E} into one on any of those other
 488      * classes, without special elevation of privilege.
 489      * <p>
 490      * The accesses permitted to a given lookup object may be limited,
 491      * according to its set of {@link #lookupModes lookupModes},
 492      * to a subset of members normally accessible to the lookup class.
 493      * For example, the {@link MethodHandles#publicLookup publicLookup}
 494      * method produces a lookup object which is only allowed to access
 495      * public members in public classes of exported packages.
 496      * The caller sensitive method {@link MethodHandles#lookup lookup}
 497      * produces a lookup object with full capabilities relative to
 498      * its caller class, to emulate all supported bytecode behaviors.
 499      * Also, the {@link Lookup#in Lookup.in} method may produce a lookup object
 500      * with fewer access modes than the original lookup object.
 501      *
 502      * <p style="font-size:smaller;">
 503      * <a id="privacc"></a>
 504      * <em>Discussion of private access:</em>
 505      * We say that a lookup has <em>private access</em>
 506      * if its {@linkplain #lookupModes lookup modes}
 507      * include the possibility of accessing {@code private} members
 508      * (which includes the private members of nestmates).
 509      * As documented in the relevant methods elsewhere,
 510      * only lookups with private access possess the following capabilities:
 511      * <ul style="font-size:smaller;">
 512      * <li>access private fields, methods, and constructors of the lookup class and its nestmates
 513      * <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods,
 514      *     such as {@code Class.forName}
 515      * <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
 516      * <li>avoid <a href="MethodHandles.Lookup.html#secmgr">package access checks</a>
 517      *     for classes accessible to the lookup class
 518      * <li>create {@link Lookup#in delegated lookup objects} which have private access to other classes
 519      *     within the same package member
 520      * </ul>
 521      * <p style="font-size:smaller;">
 522      * Each of these permissions is a consequence of the fact that a lookup object
 523      * with private access can be securely traced back to an originating class,
 524      * whose <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> and Java language access permissions
 525      * can be reliably determined and emulated by method handles.
 526      *
 527      * <h1><a id="secmgr"></a>Security manager interactions</h1>
 528      * Although bytecode instructions can only refer to classes in
 529      * a related class loader, this API can search for methods in any
 530      * class, as long as a reference to its {@code Class} object is
 531      * available.  Such cross-loader references are also possible with the
 532      * Core Reflection API, and are impossible to bytecode instructions


 717         public Class<?> lookupClass() {
 718             return lookupClass;
 719         }
 720 
 721         // This is just for calling out to MethodHandleImpl.
 722         private Class<?> lookupClassOrNull() {
 723             return (allowedModes == TRUSTED) ? null : lookupClass;
 724         }
 725 
 726         /** Tells which access-protection classes of members this lookup object can produce.
 727          *  The result is a bit-mask of the bits
 728          *  {@linkplain #PUBLIC PUBLIC (0x01)},
 729          *  {@linkplain #PRIVATE PRIVATE (0x02)},
 730          *  {@linkplain #PROTECTED PROTECTED (0x04)},
 731          *  {@linkplain #PACKAGE PACKAGE (0x08)},
 732          *  {@linkplain #MODULE MODULE (0x10)},
 733          *  and {@linkplain #UNCONDITIONAL UNCONDITIONAL (0x20)}.
 734          *  <p>
 735          *  A freshly-created lookup object
 736          *  on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has
 737          *  all possible bits set, except {@code UNCONDITIONAL}.


 738          *  A lookup object on a new lookup class
 739          *  {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
 740          *  may have some mode bits set to zero.
 741          *  Mode bits can also be
 742          *  {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}.
 743          *  Once cleared, mode bits cannot be restored from the downgraded lookup object.
 744          *  The purpose of this is to restrict access via the new lookup object,
 745          *  so that it can access only names which can be reached by the original
 746          *  lookup object, and also by the new lookup class.
 747          *  @return the lookup modes, which limit the kinds of access performed by this lookup object
 748          *  @see #in
 749          *  @see #dropLookupMode
 750          *
 751          *  @revised 9
 752          *  @spec JPMS
 753          */
 754         public int lookupModes() {
 755             return allowedModes & ALL_MODES;
 756         }
 757 


1093          *                                or if the method is not {@code static},
1094          *                                or if the method's variable arity modifier bit
1095          *                                is set and {@code asVarargsCollector} fails
1096          * @exception SecurityException if a security manager is present and it
1097          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1098          * @throws NullPointerException if any argument is null
1099          */
1100         public
1101         MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
1102             MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);
1103             return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerClass(method));
1104         }
1105 
1106         /**
1107          * Produces a method handle for a virtual method.
1108          * The type of the method handle will be that of the method,
1109          * with the receiver type (usually {@code refc}) prepended.
1110          * The method and all its argument types must be accessible to the lookup object.
1111          * <p>
1112          * When called, the handle will treat the first argument as a receiver
1113          * and, for non-private methods, dispatch on the receiver's type to determine which method
1114          * implementation to enter.
1115          * For private methods the named method in {@code refc} will be invoked on the receiver.
1116          * (The dispatching action is identical with that performed by an
1117          * {@code invokevirtual} or {@code invokeinterface} instruction.)
1118          * <p>
1119          * The first argument will be of type {@code refc} if the lookup
1120          * class has full privileges to access the member.  Otherwise
1121          * the member must be {@code protected} and the first argument
1122          * will be restricted in type to the lookup class.
1123          * <p>
1124          * The returned method handle will have
1125          * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
1126          * the method's variable arity modifier bit ({@code 0x0080}) is set.
1127          * <p>
1128          * Because of the general <a href="MethodHandles.Lookup.html#equiv">equivalence</a> between {@code invokevirtual}
1129          * instructions and method handles produced by {@code findVirtual},
1130          * if the class is {@code MethodHandle} and the name string is
1131          * {@code invokeExact} or {@code invoke}, the resulting
1132          * method handle is equivalent to one produced by
1133          * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
1134          * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
1135          * with the same {@code type} argument.


1159 MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class,
1160   "subSequence", methodType(CharSequence.class, int.class, int.class));
1161 assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString());
1162 // constructor "internal method" must be accessed differently:
1163 MethodType MT_newString = methodType(void.class); //()V for new String()
1164 try { assertEquals("impossible", lookup()
1165         .findVirtual(String.class, "<init>", MT_newString));
1166  } catch (NoSuchMethodException ex) { } // OK
1167 MethodHandle MH_newString = publicLookup()
1168   .findConstructor(String.class, MT_newString);
1169 assertEquals("", (String) MH_newString.invokeExact());
1170          * }</pre></blockquote>
1171          *
1172          * @param refc the class or interface from which the method is accessed
1173          * @param name the name of the method
1174          * @param type the type of the method, with the receiver argument omitted
1175          * @return the desired method handle
1176          * @throws NoSuchMethodException if the method does not exist
1177          * @throws IllegalAccessException if access checking fails,
1178          *                                or if the method is {@code static},

1179          *                                or if the method's variable arity modifier bit
1180          *                                is set and {@code asVarargsCollector} fails
1181          * @exception SecurityException if a security manager is present and it
1182          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1183          * @throws NullPointerException if any argument is null
1184          */
1185         public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
1186             if (refc == MethodHandle.class) {
1187                 MethodHandle mh = findVirtualForMH(name, type);
1188                 if (mh != null)  return mh;
1189             } else if (refc == VarHandle.class) {
1190                 MethodHandle mh = findVirtualForVH(name, type);
1191                 if (mh != null)  return mh;
1192             }
1193             byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
1194             MemberName method = resolveOrFail(refKind, refc, name, type);
1195             return getDirectMethod(refKind, refc, method, findBoundCallerClass(method));
1196         }
1197         private MethodHandle findVirtualForMH(String name, MethodType type) {
1198             // these names require special lookups because of the implicit MethodType argument


2212             // check the class first:
2213             boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
2214                                (defc == refc ||
2215                                 Modifier.isPublic(refc.getModifiers())));
2216             if (!classOK && (allowedModes & PACKAGE) != 0) {
2217                 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), FULL_POWER_MODES) &&
2218                            (defc == refc ||
2219                             VerifyAccess.isClassAccessible(refc, lookupClass(), FULL_POWER_MODES)));
2220             }
2221             if (!classOK)
2222                 return "class is not public";
2223             if (Modifier.isPublic(mods))
2224                 return "access to public member failed";  // (how?, module not readable?)
2225             if (Modifier.isPrivate(mods))
2226                 return "member is private";
2227             if (Modifier.isProtected(mods))
2228                 return "member is protected";
2229             return "member is private to package";
2230         }
2231 


2232         private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
2233             int allowedModes = this.allowedModes;
2234             if (allowedModes == TRUSTED)  return;
2235             if (!hasPrivateAccess()
2236                 || (specialCaller != lookupClass()
2237                        // ensure non-abstract methods in superinterfaces can be special-invoked
2238                     && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))))


2239                 throw new MemberName(specialCaller).
2240                     makeAccessException("no private access for invokespecial", this);
2241         }
2242 
2243         private boolean restrictProtectedReceiver(MemberName method) {
2244             // The accessing class only has the right to use a protected member
2245             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
2246             if (!method.isProtected() || method.isStatic()
2247                 || allowedModes == TRUSTED
2248                 || method.getDeclaringClass() == lookupClass()
2249                 || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass()))


2250                 return false;
2251             return true;
2252         }
2253         private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
2254             assert(!method.isStatic());
2255             // receiver type of mh is too wide; narrow to caller
2256             if (!method.getDeclaringClass().isAssignableFrom(caller)) {
2257                 throw method.makeAccessException("caller class must be a subclass below the method", caller);
2258             }
2259             MethodType rawType = mh.type();
2260             if (caller.isAssignableFrom(rawType.parameterType(0))) return mh; // no need to restrict; already narrow
2261             MethodType narrowType = rawType.changeParameterType(0, caller);
2262             assert(!mh.isVarargsCollector());  // viewAsType will lose varargs-ness
2263             assert(mh.viewAsTypeChecks(narrowType, true));
2264             return mh.copyWith(narrowType, mh.form);
2265         }
2266 
2267         /** Check access and get the requested method. */
2268         private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> boundCallerClass) throws IllegalAccessException {
2269             final boolean doRestrict    = true;
2270             final boolean checkSecurity = true;
2271             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, boundCallerClass);
2272         }
2273         /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */
2274         private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class<?> refc, MemberName method, Class<?> boundCallerClass) throws IllegalAccessException {
2275             final boolean doRestrict    = false;
2276             final boolean checkSecurity = true;
2277             return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, boundCallerClass);
2278         }
2279         /** Check access and get the requested method, eliding security manager checks. */
2280         private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> boundCallerClass) throws IllegalAccessException {
2281             final boolean doRestrict    = true;
2282             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
2283             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, boundCallerClass);
2284         }
2285         /** Common code for all methods; do not call directly except from immediately above. */
2286         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
2287                                                    boolean checkSecurity,
2288                                                    boolean doRestrict, Class<?> boundCallerClass) throws IllegalAccessException {
2289 
2290             checkMethod(refKind, refc, method);
2291             // Optionally check with the security manager; this isn't needed for unreflect* calls.
2292             if (checkSecurity)
2293                 checkSecurityManager(refc, method);
2294             assert(!method.isMethodHandleInvoke());
2295 
2296             if (refKind == REF_invokeSpecial &&
2297                 refc != lookupClass() &&
2298                 !refc.isInterface() &&
2299                 refc != lookupClass().getSuperclass() &&
2300                 refc.isAssignableFrom(lookupClass())) {
2301                 assert(!method.getName().equals("<init>"));  // not this code path
2302 
2303                 // Per JVMS 6.5, desc. of invokespecial instruction:
2304                 // If the method is in a superclass of the LC,
2305                 // and if our original search was above LC.super,
2306                 // repeat the search (symbolic lookup) from LC.super
2307                 // and continue with the direct superclass of that class,
2308                 // and so forth, until a match is found or no further superclasses exist.
2309                 // FIXME: MemberName.resolve should handle this instead.
2310                 Class<?> refcAsSuper = lookupClass();
2311                 MemberName m2;
2312                 do {
2313                     refcAsSuper = refcAsSuper.getSuperclass();
2314                     m2 = new MemberName(refcAsSuper,
2315                                         method.getName(),
2316                                         method.getMethodType(),
2317                                         REF_invokeSpecial);
2318                     m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
2319                 } while (m2 == null &&         // no method is found yet
2320                          refc != refcAsSuper); // search up to refc
2321                 if (m2 == null)  throw new InternalError(method.toString());
2322                 method = m2;


< prev index next >