1689 * @see #findVirtual |
1689 * @see #findVirtual |
1690 */ |
1690 */ |
1691 public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
1691 public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
1692 Class<? extends Object> refc = receiver.getClass(); // may get NPE |
1692 Class<? extends Object> refc = receiver.getClass(); // may get NPE |
1693 MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); |
1693 MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); |
1694 MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method)); |
1694 MethodHandle mh = getDirectMethodNoRestrictInvokeSpecial(refc, method, findBoundCallerClass(method)); |
|
1695 if (!mh.type().leadingReferenceParameter().isAssignableFrom(receiver.getClass())) { |
|
1696 throw new IllegalAccessException("The restricted defining class " + |
|
1697 mh.type().leadingReferenceParameter().getName() + |
|
1698 " is not assignable from receiver class " + |
|
1699 receiver.getClass().getName()); |
|
1700 } |
1695 return mh.bindArgumentL(0, receiver).setVarargs(method); |
1701 return mh.bindArgumentL(0, receiver).setVarargs(method); |
1696 } |
1702 } |
1697 |
1703 |
1698 /** |
1704 /** |
1699 * Makes a <a href="MethodHandleInfo.html#directmh">direct method handle</a> |
1705 * Makes a <a href="MethodHandleInfo.html#directmh">direct method handle</a> |
2238 // receiver type of mh is too wide; narrow to caller |
2244 // receiver type of mh is too wide; narrow to caller |
2239 if (!method.getDeclaringClass().isAssignableFrom(caller)) { |
2245 if (!method.getDeclaringClass().isAssignableFrom(caller)) { |
2240 throw method.makeAccessException("caller class must be a subclass below the method", caller); |
2246 throw method.makeAccessException("caller class must be a subclass below the method", caller); |
2241 } |
2247 } |
2242 MethodType rawType = mh.type(); |
2248 MethodType rawType = mh.type(); |
2243 if (rawType.parameterType(0) == caller) return mh; |
2249 if (caller.isAssignableFrom(rawType.parameterType(0))) return mh; // no need to restrict; already narrow |
2244 MethodType narrowType = rawType.changeParameterType(0, caller); |
2250 MethodType narrowType = rawType.changeParameterType(0, caller); |
2245 assert(!mh.isVarargsCollector()); // viewAsType will lose varargs-ness |
2251 assert(!mh.isVarargsCollector()); // viewAsType will lose varargs-ness |
2246 assert(mh.viewAsTypeChecks(narrowType, true)); |
2252 assert(mh.viewAsTypeChecks(narrowType, true)); |
2247 return mh.copyWith(narrowType, mh.form); |
2253 return mh.copyWith(narrowType, mh.form); |
2248 } |
2254 } |
2251 private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { |
2257 private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { |
2252 final boolean doRestrict = true; |
2258 final boolean doRestrict = true; |
2253 final boolean checkSecurity = true; |
2259 final boolean checkSecurity = true; |
2254 return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass); |
2260 return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass); |
2255 } |
2261 } |
2256 /** Check access and get the requested method, eliding receiver narrowing rules. */ |
2262 /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */ |
2257 private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { |
2263 private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { |
2258 final boolean doRestrict = false; |
2264 final boolean doRestrict = false; |
2259 final boolean checkSecurity = true; |
2265 final boolean checkSecurity = true; |
2260 return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass); |
2266 return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerClass); |
2261 } |
2267 } |
2262 /** Check access and get the requested method, eliding security manager checks. */ |
2268 /** Check access and get the requested method, eliding security manager checks. */ |
2263 private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { |
2269 private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { |
2264 final boolean doRestrict = true; |
2270 final boolean doRestrict = true; |
2265 final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants |
2271 final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants |
2307 } |
2313 } |
2308 |
2314 |
2309 DirectMethodHandle dmh = DirectMethodHandle.make(refKind, refc, method); |
2315 DirectMethodHandle dmh = DirectMethodHandle.make(refKind, refc, method); |
2310 MethodHandle mh = dmh; |
2316 MethodHandle mh = dmh; |
2311 // Optionally narrow the receiver argument to refc using restrictReceiver. |
2317 // Optionally narrow the receiver argument to refc using restrictReceiver. |
2312 if (doRestrict && |
2318 if ((doRestrict && refKind == REF_invokeSpecial) || |
2313 (refKind == REF_invokeSpecial || |
2319 (MethodHandleNatives.refKindHasReceiver(refKind) && restrictProtectedReceiver(method))) { |
2314 (MethodHandleNatives.refKindHasReceiver(refKind) && |
|
2315 restrictProtectedReceiver(method)))) { |
|
2316 mh = restrictReceiver(method, dmh, lookupClass()); |
2320 mh = restrictReceiver(method, dmh, lookupClass()); |
2317 } |
2321 } |
2318 mh = maybeBindCaller(method, mh, callerClass); |
2322 mh = maybeBindCaller(method, mh, callerClass); |
2319 mh = mh.setVarargs(method); |
2323 mh = mh.setVarargs(method); |
2320 return mh; |
2324 return mh; |