596 */ |
596 */ |
597 public |
597 public |
598 MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
598 MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
599 MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); |
599 MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); |
600 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
600 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
601 return getDirectMethod(REF_invokeStatic, refc, method); |
601 Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor |
|
602 return getDirectMethod(REF_invokeStatic, refc, method, callerClass); |
602 } |
603 } |
603 |
604 |
604 /** |
605 /** |
605 * Produces a method handle for a virtual method. |
606 * Produces a method handle for a virtual method. |
606 * The type of the method handle will be that of the method, |
607 * The type of the method handle will be that of the method, |
650 if (mh != null) return mh; |
651 if (mh != null) return mh; |
651 } |
652 } |
652 byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); |
653 byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); |
653 MemberName method = resolveOrFail(refKind, refc, name, type); |
654 MemberName method = resolveOrFail(refKind, refc, name, type); |
654 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
655 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
655 return getDirectMethod(refKind, refc, method); |
656 Class<?> callerClass = findBoundCallerClass(method); |
|
657 return getDirectMethod(refKind, refc, method, callerClass); |
656 } |
658 } |
657 private MethodHandle findVirtualForMH(String name, MethodType type) { |
659 private MethodHandle findVirtualForMH(String name, MethodType type) { |
658 // these names require special lookups because of the implicit MethodType argument |
660 // these names require special lookups because of the implicit MethodType argument |
659 if ("invoke".equals(name)) |
661 if ("invoke".equals(name)) |
660 return invoker(type); |
662 return invoker(type); |
734 Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { |
736 Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { |
735 checkSpecialCaller(specialCaller); |
737 checkSpecialCaller(specialCaller); |
736 Lookup specialLookup = this.in(specialCaller); |
738 Lookup specialLookup = this.in(specialCaller); |
737 MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); |
739 MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); |
738 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
740 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
739 return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method); |
741 Class<?> callerClass = findBoundCallerClass(method); |
|
742 return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, callerClass); |
740 } |
743 } |
741 |
744 |
742 /** |
745 /** |
743 * Produces a method handle giving read access to a non-static field. |
746 * Produces a method handle giving read access to a non-static field. |
744 * The type of the method handle will have a return type of the field's |
747 * The type of the method handle will have a return type of the field's |
877 */ |
880 */ |
878 public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
881 public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
879 Class<? extends Object> refc = receiver.getClass(); // may get NPE |
882 Class<? extends Object> refc = receiver.getClass(); // may get NPE |
880 MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); |
883 MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); |
881 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
884 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
882 MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method); |
885 Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor |
|
886 MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, callerClass); |
883 return mh.bindReceiver(receiver).setVarargs(method); |
887 return mh.bindReceiver(receiver).setVarargs(method); |
884 } |
888 } |
885 |
889 |
886 /** |
890 /** |
887 * Makes a direct method handle to <i>m</i>, if the lookup class has permission. |
891 * Makes a direct method handle to <i>m</i>, if the lookup class has permission. |
908 MemberName method = new MemberName(m); |
912 MemberName method = new MemberName(m); |
909 byte refKind = method.getReferenceKind(); |
913 byte refKind = method.getReferenceKind(); |
910 if (refKind == REF_invokeSpecial) |
914 if (refKind == REF_invokeSpecial) |
911 refKind = REF_invokeVirtual; |
915 refKind = REF_invokeVirtual; |
912 assert(method.isMethod()); |
916 assert(method.isMethod()); |
|
917 Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor |
913 Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; |
918 Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; |
914 return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method); |
919 return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass); |
915 } |
920 } |
916 |
921 |
917 /** |
922 /** |
918 * Produces a method handle for a reflected method. |
923 * Produces a method handle for a reflected method. |
919 * It will bypass checks for overriding methods on the receiver, |
924 * It will bypass checks for overriding methods on the receiver, |
938 public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { |
943 public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { |
939 checkSpecialCaller(specialCaller); |
944 checkSpecialCaller(specialCaller); |
940 Lookup specialLookup = this.in(specialCaller); |
945 Lookup specialLookup = this.in(specialCaller); |
941 MemberName method = new MemberName(m, true); |
946 MemberName method = new MemberName(m, true); |
942 assert(method.isMethod()); |
947 assert(method.isMethod()); |
|
948 Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor |
943 // ignore m.isAccessible: this is a new kind of access |
949 // ignore m.isAccessible: this is a new kind of access |
944 return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method); |
950 return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass); |
945 } |
951 } |
946 |
952 |
947 /** |
953 /** |
948 * Produces a method handle for a reflected constructor. |
954 * Produces a method handle for a reflected constructor. |
949 * The type of the method handle will be that of the constructor, |
955 * The type of the method handle will be that of the constructor, |
1038 if (caller != null && !VerifyAccess.isClassAccessible(refc, caller, allowedModes)) |
1044 if (caller != null && !VerifyAccess.isClassAccessible(refc, caller, allowedModes)) |
1039 throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this); |
1045 throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this); |
1040 } |
1046 } |
1041 |
1047 |
1042 /** |
1048 /** |
|
1049 * Find my trustable caller class if m is a caller sensitive method. |
|
1050 * If this lookup object has private access, then the caller class is the lookupClass. |
|
1051 * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). |
|
1052 * This is the same caller class as is used by checkSecurityManager. |
|
1053 * This function performs stack walk magic: do not refactor it. |
|
1054 */ |
|
1055 Class<?> findBoundCallerClass(MemberName m) { |
|
1056 Class<?> callerClass = null; |
|
1057 if (MethodHandleNatives.isCallerSensitive(m)) { |
|
1058 // Do not refactor this to a more "logical" place, since it is stack walk magic. |
|
1059 // Note that this is the same expression as in Step 2 below in checkSecurityManager. |
|
1060 callerClass = ((allowedModes & PRIVATE) != 0 |
|
1061 ? lookupClass // for strong access modes, no extra check |
|
1062 // next line does stack walk magic; do not refactor: |
|
1063 : getCallerClassAtEntryPoint(true)); |
|
1064 } |
|
1065 return callerClass; |
|
1066 } |
|
1067 /** |
1043 * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>. |
1068 * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>. |
|
1069 * Determines a trustable caller class to compare with refc, the symbolic reference class. |
|
1070 * If this lookup object has private access, then the caller class is the lookupClass. |
|
1071 * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). |
1044 * This function performs stack walk magic: do not refactor it. |
1072 * This function performs stack walk magic: do not refactor it. |
1045 */ |
1073 */ |
1046 void checkSecurityManager(Class<?> refc, MemberName m) { |
1074 void checkSecurityManager(Class<?> refc, MemberName m) { |
1047 SecurityManager smgr = System.getSecurityManager(); |
1075 SecurityManager smgr = System.getSecurityManager(); |
1048 if (smgr == null) return; |
1076 if (smgr == null) return; |
1193 if (rawType.parameterType(0) == caller) return mh; |
1221 if (rawType.parameterType(0) == caller) return mh; |
1194 MethodType narrowType = rawType.changeParameterType(0, caller); |
1222 MethodType narrowType = rawType.changeParameterType(0, caller); |
1195 return mh.viewAsType(narrowType); |
1223 return mh.viewAsType(narrowType); |
1196 } |
1224 } |
1197 |
1225 |
1198 private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method) throws IllegalAccessException { |
1226 private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { |
1199 return getDirectMethodCommon(refKind, refc, method, |
1227 return getDirectMethodCommon(refKind, refc, method, |
1200 (refKind == REF_invokeSpecial || |
1228 (refKind == REF_invokeSpecial || |
1201 (MethodHandleNatives.refKindHasReceiver(refKind) && |
1229 (MethodHandleNatives.refKindHasReceiver(refKind) && |
1202 restrictProtectedReceiver(method)))); |
1230 restrictProtectedReceiver(method))), callerClass); |
1203 } |
1231 } |
1204 private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method) throws IllegalAccessException { |
1232 private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { |
1205 return getDirectMethodCommon(refKind, refc, method, false); |
1233 return getDirectMethodCommon(refKind, refc, method, false, callerClass); |
1206 } |
1234 } |
1207 private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method, |
1235 private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method, |
1208 boolean doRestrict) throws IllegalAccessException { |
1236 boolean doRestrict, Class<?> callerClass) throws IllegalAccessException { |
1209 checkMethod(refKind, refc, method); |
1237 checkMethod(refKind, refc, method); |
1210 if (method.isMethodHandleInvoke()) |
1238 if (method.isMethodHandleInvoke()) |
1211 return fakeMethodHandleInvoke(method); |
1239 return fakeMethodHandleInvoke(method); |
1212 MethodHandle mh = DirectMethodHandle.make(refc, method); |
1240 MethodHandle mh = DirectMethodHandle.make(refc, method); |
1213 mh = maybeBindCaller(method, mh); |
1241 mh = maybeBindCaller(method, mh, callerClass); |
1214 mh = mh.setVarargs(method); |
1242 mh = mh.setVarargs(method); |
1215 if (doRestrict) |
1243 if (doRestrict) |
1216 mh = restrictReceiver(method, mh, lookupClass()); |
1244 mh = restrictReceiver(method, mh, lookupClass()); |
1217 return mh; |
1245 return mh; |
1218 } |
1246 } |
1219 private MethodHandle fakeMethodHandleInvoke(MemberName method) { |
1247 private MethodHandle fakeMethodHandleInvoke(MemberName method) { |
1220 return throwException(method.getReturnType(), UnsupportedOperationException.class); |
1248 return throwException(method.getReturnType(), UnsupportedOperationException.class); |
1221 } |
1249 } |
1222 private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh) throws IllegalAccessException { |
1250 private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh, |
|
1251 Class<?> callerClass) |
|
1252 throws IllegalAccessException { |
1223 if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method)) |
1253 if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method)) |
1224 return mh; |
1254 return mh; |
1225 Class<?> hostClass = lookupClass; |
1255 Class<?> hostClass = lookupClass; |
1226 if ((allowedModes & PRIVATE) == 0) // caller must use full-power lookup |
1256 if ((allowedModes & PRIVATE) == 0) // caller must use full-power lookup |
1227 hostClass = null; |
1257 hostClass = callerClass; // callerClass came from a security manager style stack walk |
1228 MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass); |
1258 MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass); |
1229 // Note: caller will apply varargs after this step happens. |
1259 // Note: caller will apply varargs after this step happens. |
1230 return cbmh; |
1260 return cbmh; |
1231 } |
1261 } |
1232 private MethodHandle getDirectField(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException { |
1262 private MethodHandle getDirectField(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException { |
1260 : resolveOrFail(refKind, defc, name, (Class<?>) type); |
1290 : resolveOrFail(refKind, defc, name, (Class<?>) type); |
1261 return getDirectField(refKind, defc, field); |
1291 return getDirectField(refKind, defc, field); |
1262 } else if (MethodHandleNatives.refKindIsMethod(refKind)) { |
1292 } else if (MethodHandleNatives.refKindIsMethod(refKind)) { |
1263 MemberName method = (resolved != null) ? resolved |
1293 MemberName method = (resolved != null) ? resolved |
1264 : resolveOrFail(refKind, defc, name, (MethodType) type); |
1294 : resolveOrFail(refKind, defc, name, (MethodType) type); |
1265 return getDirectMethod(refKind, defc, method); |
1295 return getDirectMethod(refKind, defc, method, lookupClass); |
1266 } else if (refKind == REF_newInvokeSpecial) { |
1296 } else if (refKind == REF_newInvokeSpecial) { |
1267 assert(name == null || name.equals("<init>")); |
1297 assert(name == null || name.equals("<init>")); |
1268 MemberName ctor = (resolved != null) ? resolved |
1298 MemberName ctor = (resolved != null) ? resolved |
1269 : resolveOrFail(REF_newInvokeSpecial, defc, name, (MethodType) type); |
1299 : resolveOrFail(REF_newInvokeSpecial, defc, name, (MethodType) type); |
1270 return getDirectConstructor(defc, ctor); |
1300 return getDirectConstructor(defc, ctor); |