1161 * <p> 1162 * The returned method handle will have 1163 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1164 * the method's variable arity modifier bit ({@code 0x0080}) is set. 1165 * <p> 1166 * If <i>m</i> is static, and 1167 * if the returned method handle is invoked, the method's class will 1168 * be initialized, if it has not already been initialized. 1169 * @param m the reflected method 1170 * @return a method handle which can invoke the reflected method 1171 * @throws IllegalAccessException if access checking fails 1172 * or if the method's variable arity modifier bit 1173 * is set and {@code asVarargsCollector} fails 1174 * @throws NullPointerException if the argument is null 1175 */ 1176 public MethodHandle unreflect(Method m) throws IllegalAccessException { 1177 if (m.getDeclaringClass() == MethodHandle.class) { 1178 MethodHandle mh = unreflectForMH(m); 1179 if (mh != null) return mh; 1180 } 1181 MemberName method = new MemberName(m); 1182 byte refKind = method.getReferenceKind(); 1183 if (refKind == REF_invokeSpecial) 1184 refKind = REF_invokeVirtual; 1185 assert(method.isMethod()); 1186 Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; 1187 return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method)); 1188 } 1189 private MethodHandle unreflectForMH(Method m) { 1190 // these names require special lookups because they throw UnsupportedOperationException 1191 if (MemberName.isMethodHandleInvokeName(m.getName())) 1192 return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m)); 1193 return null; 1194 } 1195 1196 /** 1197 * Produces a method handle for a reflected method. 1198 * It will bypass checks for overriding methods on the receiver, 1199 * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial} 1200 * instruction from within the explicitly specified {@code specialCaller}. 1201 * The type of the method handle will be that of the method, 1202 * with a suitably restricted receiver type prepended. 1203 * (The receiver type will be {@code specialCaller} or a subtype.) 1204 * If the method's {@code accessible} flag is not set, 1205 * access checking is performed immediately on behalf of the lookup class, 1206 * as if {@code invokespecial} instruction were being linked. 1207 * <p> 1208 * Before method resolution, 1209 * if the explicitly specified caller class is not identical with the 1210 * lookup class, or if this lookup object does not have 1211 * <a href="MethodHandles.Lookup.html#privacc">private access</a> 1212 * privileges, the access fails. 1213 * <p> 1214 * The returned method handle will have 1215 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1216 * the method's variable arity modifier bit ({@code 0x0080}) is set. 1217 * @param m the reflected method 1218 * @param specialCaller the class nominally calling the method 1219 * @return a method handle which can invoke the reflected method 1220 * @throws IllegalAccessException if access checking fails 1221 * or if the method's variable arity modifier bit 1222 * is set and {@code asVarargsCollector} fails 1223 * @throws NullPointerException if any argument is null 1224 */ 1225 public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { 1226 checkSpecialCaller(specialCaller); 1227 Lookup specialLookup = this.in(specialCaller); 1228 MemberName method = new MemberName(m, true); 1229 assert(method.isMethod()); 1230 // ignore m.isAccessible: this is a new kind of access 1231 return specialLookup.getDirectMethodNoSecurityManager(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerClass(method)); 1232 } 1233 1234 /** 1235 * Produces a method handle for a reflected constructor. 1236 * The type of the method handle will be that of the constructor, 1237 * with the return type changed to the declaring class. 1238 * The method handle will perform a {@code newInstance} operation, 1239 * creating a new instance of the constructor's class on the 1240 * arguments passed to the method handle. 1241 * <p> 1242 * If the constructor's {@code accessible} flag is not set, 1243 * access checking is performed immediately on behalf of the lookup class. 1244 * <p> 1245 * The returned method handle will have 1246 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1247 * the constructor's variable arity modifier bit ({@code 0x0080}) is set. 1248 * <p> 1249 * If the returned method handle is invoked, the constructor's class will 1250 * be initialized, if it has not already been initialized. 1251 * @param c the reflected constructor 1252 * @return a method handle which can invoke the reflected constructor 1253 * @throws IllegalAccessException if access checking fails 1254 * or if the method's variable arity modifier bit 1255 * is set and {@code asVarargsCollector} fails 1256 * @throws NullPointerException if the argument is null 1257 */ 1258 public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException { 1259 MemberName ctor = new MemberName(c); 1260 assert(ctor.isConstructor()); 1261 Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this; 1262 return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor); 1263 } 1264 1265 /** 1266 * Produces a method handle giving read access to a reflected field. 1267 * The type of the method handle will have a return type of the field's 1268 * value type. 1269 * If the field is static, the method handle will take no arguments. 1270 * Otherwise, its single argument will be the instance containing 1271 * the field. 1272 * If the field's {@code accessible} flag is not set, 1273 * access checking is performed immediately on behalf of the lookup class. 1274 * <p> 1275 * If the field is static, and 1276 * if the returned method handle is invoked, the field's class will 1277 * be initialized, if it has not already been initialized. 1278 * @param f the reflected field 1279 * @return a method handle which can load values from the reflected field 1280 * @throws IllegalAccessException if access checking fails 1281 * @throws NullPointerException if the argument is null 1282 */ 1283 public MethodHandle unreflectGetter(Field f) throws IllegalAccessException { 1284 return unreflectField(f, false); 1285 } 1286 private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException { 1287 MemberName field = new MemberName(f, isSetter); 1288 assert(isSetter 1289 ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind()) 1290 : MethodHandleNatives.refKindIsGetter(field.getReferenceKind())); 1291 Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this; 1292 return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field); 1293 } 1294 1295 /** 1296 * Produces a method handle giving write access to a reflected field. 1297 * The type of the method handle will have a void return type. 1298 * If the field is static, the method handle will take a single 1299 * argument, of the field's value type, the value to be stored. 1300 * Otherwise, the two arguments will be the instance containing 1301 * the field, and the value to be stored. 1302 * If the field's {@code accessible} flag is not set, 1303 * access checking is performed immediately on behalf of the lookup class. 1304 * <p> 1305 * If the field is static, and 1306 * if the returned method handle is invoked, the field's class will 1307 * be initialized, if it has not already been initialized. | 1161 * <p> 1162 * The returned method handle will have 1163 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1164 * the method's variable arity modifier bit ({@code 0x0080}) is set. 1165 * <p> 1166 * If <i>m</i> is static, and 1167 * if the returned method handle is invoked, the method's class will 1168 * be initialized, if it has not already been initialized. 1169 * @param m the reflected method 1170 * @return a method handle which can invoke the reflected method 1171 * @throws IllegalAccessException if access checking fails 1172 * or if the method's variable arity modifier bit 1173 * is set and {@code asVarargsCollector} fails 1174 * @throws NullPointerException if the argument is null 1175 */ 1176 public MethodHandle unreflect(Method m) throws IllegalAccessException { 1177 if (m.getDeclaringClass() == MethodHandle.class) { 1178 MethodHandle mh = unreflectForMH(m); 1179 if (mh != null) return mh; 1180 } 1181 MemberName method = MemberName.make(m); 1182 byte refKind = method.getReferenceKind(); 1183 if (refKind == REF_invokeSpecial) 1184 refKind = REF_invokeVirtual; 1185 assert(method.isMethod()); 1186 Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; 1187 return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method)); 1188 } 1189 private MethodHandle unreflectForMH(Method m) { 1190 // these names require special lookups because they throw UnsupportedOperationException 1191 if (MemberName.isMethodHandleInvokeName(m.getName())) 1192 return MethodHandleImpl.fakeMethodHandleInvoke(MemberName.make(m)); 1193 return null; 1194 } 1195 1196 /** 1197 * Produces a method handle for a reflected method. 1198 * It will bypass checks for overriding methods on the receiver, 1199 * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial} 1200 * instruction from within the explicitly specified {@code specialCaller}. 1201 * The type of the method handle will be that of the method, 1202 * with a suitably restricted receiver type prepended. 1203 * (The receiver type will be {@code specialCaller} or a subtype.) 1204 * If the method's {@code accessible} flag is not set, 1205 * access checking is performed immediately on behalf of the lookup class, 1206 * as if {@code invokespecial} instruction were being linked. 1207 * <p> 1208 * Before method resolution, 1209 * if the explicitly specified caller class is not identical with the 1210 * lookup class, or if this lookup object does not have 1211 * <a href="MethodHandles.Lookup.html#privacc">private access</a> 1212 * privileges, the access fails. 1213 * <p> 1214 * The returned method handle will have 1215 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1216 * the method's variable arity modifier bit ({@code 0x0080}) is set. 1217 * @param m the reflected method 1218 * @param specialCaller the class nominally calling the method 1219 * @return a method handle which can invoke the reflected method 1220 * @throws IllegalAccessException if access checking fails 1221 * or if the method's variable arity modifier bit 1222 * is set and {@code asVarargsCollector} fails 1223 * @throws NullPointerException if any argument is null 1224 */ 1225 public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { 1226 checkSpecialCaller(specialCaller); 1227 Lookup specialLookup = this.in(specialCaller); 1228 MemberName method = MemberName.make(m, true); 1229 assert(method.isMethod()); 1230 // ignore m.isAccessible: this is a new kind of access 1231 return specialLookup.getDirectMethodNoSecurityManager(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerClass(method)); 1232 } 1233 1234 /** 1235 * Produces a method handle for a reflected constructor. 1236 * The type of the method handle will be that of the constructor, 1237 * with the return type changed to the declaring class. 1238 * The method handle will perform a {@code newInstance} operation, 1239 * creating a new instance of the constructor's class on the 1240 * arguments passed to the method handle. 1241 * <p> 1242 * If the constructor's {@code accessible} flag is not set, 1243 * access checking is performed immediately on behalf of the lookup class. 1244 * <p> 1245 * The returned method handle will have 1246 * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if 1247 * the constructor's variable arity modifier bit ({@code 0x0080}) is set. 1248 * <p> 1249 * If the returned method handle is invoked, the constructor's class will 1250 * be initialized, if it has not already been initialized. 1251 * @param c the reflected constructor 1252 * @return a method handle which can invoke the reflected constructor 1253 * @throws IllegalAccessException if access checking fails 1254 * or if the method's variable arity modifier bit 1255 * is set and {@code asVarargsCollector} fails 1256 * @throws NullPointerException if the argument is null 1257 */ 1258 public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException { 1259 MemberName ctor = MemberName.make(c); 1260 assert(ctor.isConstructor()); 1261 Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this; 1262 return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor); 1263 } 1264 1265 /** 1266 * Produces a method handle giving read access to a reflected field. 1267 * The type of the method handle will have a return type of the field's 1268 * value type. 1269 * If the field is static, the method handle will take no arguments. 1270 * Otherwise, its single argument will be the instance containing 1271 * the field. 1272 * If the field's {@code accessible} flag is not set, 1273 * access checking is performed immediately on behalf of the lookup class. 1274 * <p> 1275 * If the field is static, and 1276 * if the returned method handle is invoked, the field's class will 1277 * be initialized, if it has not already been initialized. 1278 * @param f the reflected field 1279 * @return a method handle which can load values from the reflected field 1280 * @throws IllegalAccessException if access checking fails 1281 * @throws NullPointerException if the argument is null 1282 */ 1283 public MethodHandle unreflectGetter(Field f) throws IllegalAccessException { 1284 return unreflectField(f, false); 1285 } 1286 private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException { 1287 MemberName field = MemberName.make(f, isSetter); 1288 assert(isSetter 1289 ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind()) 1290 : MethodHandleNatives.refKindIsGetter(field.getReferenceKind())); 1291 Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this; 1292 return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field); 1293 } 1294 1295 /** 1296 * Produces a method handle giving write access to a reflected field. 1297 * The type of the method handle will have a void return type. 1298 * If the field is static, the method handle will take a single 1299 * argument, of the field's value type, the value to be stored. 1300 * Otherwise, the two arguments will be the instance containing 1301 * the field, and the value to be stored. 1302 * If the field's {@code accessible} flag is not set, 1303 * access checking is performed immediately on behalf of the lookup class. 1304 * <p> 1305 * If the field is static, and 1306 * if the returned method handle is invoked, the field's class will 1307 * be initialized, if it has not already been initialized. |