< prev index next >

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

Print this page




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.


< prev index next >