< prev index next >

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

Print this page




1245   MH_newProcessBuilder.invoke("x", "y", "z");
1246 assertEquals("[x, y, z]", pb.command().toString());
1247          * }</pre></blockquote>
1248          * @param refc the class or interface from which the method is accessed
1249          * @param type the type of the method, with the receiver argument omitted, and a void return type
1250          * @return the desired method handle
1251          * @throws NoSuchMethodException if the constructor does not exist
1252          * @throws IllegalAccessException if access checking fails
1253          *                                or if the method's variable arity modifier bit
1254          *                                is set and {@code asVarargsCollector} fails
1255          * @exception SecurityException if a security manager is present and it
1256          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1257          * @throws NullPointerException if any argument is null
1258          */
1259         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
1260             if (refc.isArray()) {
1261                 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
1262             }
1263             String name = "<init>";
1264             if (MinimalValueTypes_1_0.isValueType(refc)) {
1265                 try {
1266                     //shady: The findConstructor method of Lookup will expose all accessible constructors of the original
1267                     //value-capable class, for both the Q-type and the legacy L-type. The return type of a method handle produced
1268                     //by findConstructor will be identical with the lookup class, even if it is a Q-type.
1269                     refc = MinimalValueTypes_1_0.getValueCapableClass(refc);
1270                 } catch (ClassNotFoundException ex) {
1271                     throw new NoSuchElementException(ex.getMessage());
1272                 }
1273             }
1274             MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
1275             return getDirectConstructor(refc, ctor);
1276         }
1277 
1278         /**
1279          * Looks up a class by name from the lookup context defined by this {@code Lookup} object. The static
1280          * initializer of the class is not run.
1281          * <p>
1282          * The lookup context here is determined by the {@linkplain #lookupClass() lookup class}, its class
1283          * loader, and the {@linkplain #lookupModes() lookup modes}. In particular, the method first attempts to
1284          * load the requested class, and then determines whether the class is accessible to this lookup object.
1285          *
1286          * @param targetName the fully qualified name of the class to be looked up.
1287          * @return the requested class.
1288          * @exception SecurityException if a security manager is present and it
1289          *            <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1290          * @throws LinkageError if the linkage fails
1291          * @throws ClassNotFoundException if the class cannot be loaded by the lookup class' loader.
1292          * @throws IllegalAccessException if the class is not accessible, using the allowed access


1409         /**
1410          * Produces a method handle giving read access to a non-static field.
1411          * The type of the method handle will have a return type of the field's
1412          * value type.
1413          * The method handle's single argument will be the instance containing
1414          * the field.
1415          * Access checking is performed immediately on behalf of the lookup class.
1416          * @param refc the class or interface from which the method is accessed
1417          * @param name the field's name
1418          * @param type the field's type
1419          * @return a method handle which can load values from the field
1420          * @throws NoSuchFieldException if the field does not exist
1421          * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
1422          * @exception SecurityException if a security manager is present and it
1423          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1424          * @throws NullPointerException if any argument is null
1425          * @see #findVarHandle(Class, String, Class)
1426          */
1427         public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1428             if (MinimalValueTypes_1_0.isValueType(refc)) {
1429                 try {
1430                     return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(refc)).findGetter(this, name, type);
1431                 } catch (ReflectiveOperationException ex) {
1432                     throw new IllegalStateException(ex);
1433                 }
1434             } else {
1435                 MemberName field = resolveOrFail(REF_getField, refc, name, type);
1436                 return getDirectField(REF_getField, refc, field);
1437             }
1438         }
1439 
1440         /**
1441          * Produces a method handle giving write access to a non-static field.
1442          * The type of the method handle will have a void return type.
1443          * The method handle will take two arguments, the instance containing
1444          * the field, and the value to be stored.
1445          * The second argument will be of the field's value type.
1446          * Access checking is performed immediately on behalf of the lookup class.
1447          * @param refc the class or interface from which the method is accessed
1448          * @param name the field's name
1449          * @param type the field's type
1450          * @return a method handle which can store values into the field
1451          * @throws NoSuchFieldException if the field does not exist
1452          * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
1453          * @exception SecurityException if a security manager is present and it


2593      * The type of the method handle will have a void return type.
2594      * Its last argument will be the array's element type.
2595      * The first and second arguments will be the array type and int.
2596      * @param arrayClass the class of an array
2597      * @return a method handle which can store values into the array type
2598      * @throws NullPointerException if the argument is null
2599      * @throws IllegalArgumentException if arrayClass is not an array type
2600      */
2601     public static
2602     MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
2603         ValueType<?> compValue = valueComponent(arrayClass);
2604         return (compValue != null) ?
2605                 compValue.arraySetter() :
2606                 MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET);
2607     }
2608 
2609     @SuppressWarnings("unchecked")
2610     private static <Z> ValueType<Z> valueComponent(Class<Z> clazz) {
2611         Class<?> comp = clazz.getComponentType();
2612         if (MinimalValueTypes_1_0.isValueType(comp)) {
2613             try {
2614                 return (ValueType<Z>)ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(comp));
2615             } catch (ClassNotFoundException ex) {
2616                 throw new IllegalStateException(ex);
2617             }
2618         } else {
2619             return null;
2620         }
2621     }
2622 
2623     /**
2624      * Produces a VarHandle giving access to elements of an array of type
2625      * {@code arrayClass}.  The VarHandle's variable type is the component type
2626      * of {@code arrayClass} and the list of coordinate types is
2627      * {@code (arrayClass, int)}, where the {@code int} coordinate type
2628      * corresponds to an argument that is an index into an array.
2629      * <p>
2630      * Certain access modes of the returned VarHandle are unsupported under
2631      * the following conditions:
2632      * <ul>
2633      * <li>if the component type is anything other than {@code byte},
2634      *     {@code short}, {@code char}, {@code int}, {@code long},
2635      *     {@code float}, or {@code double} then numeric atomic update access
2636      *     modes are unsupported.
2637      * <li>if the field type is anything other than {@code boolean},


3367      * Produces a constant method handle of the requested return type which
3368      * returns the default value for that type every time it is invoked.
3369      * The resulting constant method handle will have no side effects.
3370      * <p>The returned method handle is equivalent to {@code empty(methodType(type))}.
3371      * It is also equivalent to {@code explicitCastArguments(constant(Object.class, null), methodType(type))},
3372      * since {@code explicitCastArguments} converts {@code null} to default values.
3373      * @param type the expected return type of the desired method handle
3374      * @return a constant method handle that takes no arguments
3375      *         and returns the default value of the given type (or void, if the type is void)
3376      * @throws NullPointerException if the argument is null
3377      * @see MethodHandles#constant
3378      * @see MethodHandles#empty
3379      * @see MethodHandles#explicitCastArguments
3380      * @since 9
3381      */
3382     public static MethodHandle zero(Class<?> type) {
3383         Objects.requireNonNull(type);
3384         if (type.isPrimitive()) {
3385             return zero(Wrapper.forPrimitiveType(type), type);
3386         } else if (MinimalValueTypes_1_0.isValueType(type)) {
3387             try {
3388                 return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(type)).defaultValueConstant();
3389             } catch (ClassNotFoundException ex) {
3390                 throw new IllegalStateException(ex);
3391             }
3392         } else {
3393             return zero(Wrapper.OBJECT, type);
3394         }
3395     }
3396 
3397     private static MethodHandle identityOrVoid(Class<?> type) {
3398         return type == void.class ? zero(type) : identity(type);
3399     }
3400 
3401     /**
3402      * Produces a method handle of the requested type which ignores any arguments, does nothing,
3403      * and returns a suitable default depending on the return type.
3404      * That is, it returns a zero primitive value, a {@code null}, or {@code void}.
3405      * <p>The returned method handle is equivalent to
3406      * {@code dropArguments(zero(type.returnType()), 0, type.parameterList())}.
3407      * <p>
3408      * @apiNote Given a predicate and target, a useful "if-then" construct can be produced as
3409      * {@code guardWithTest(pred, target, empty(target.type())}.
3410      * @param type the type of the desired method handle
3411      * @return a constant method handle of the given type, which returns a default value of the given return type
3412      * @throws NullPointerException if the argument is null
3413      * @see MethodHandles#zero
3414      * @see MethodHandles#constant
3415      * @since 9
3416      */
3417     public static  MethodHandle empty(MethodType type) {
3418         Objects.requireNonNull(type);
3419         return dropArguments(zero(type.returnType()), 0, type.parameterList());
3420     }
3421 
3422     private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.COUNT];
3423     private static MethodHandle makeIdentity(Class<?> ptype) {
3424         if (!MinimalValueTypes_1_0.isValueType(ptype)) {
3425             MethodType mtype = MethodType.methodType(ptype, ptype);
3426             LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
3427             return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
3428         } else {
3429             try {
3430                 return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(ptype)).identity();
3431             } catch (ReflectiveOperationException ex) {
3432                 throw new IllegalStateException(ex);
3433             }
3434         }
3435     }
3436 
3437     private static MethodHandle zero(Wrapper btw, Class<?> rtype) {
3438         int pos = btw.ordinal();
3439         MethodHandle zero = ZERO_MHS[pos];
3440         if (zero == null) {
3441             zero = setCachedMethodHandle(ZERO_MHS, pos, makeZero(btw.primitiveType()));
3442         }
3443         if (zero.type().returnType() == rtype)
3444             return zero;
3445         assert(btw == Wrapper.OBJECT);
3446         return makeZero(rtype);
3447     }
3448     private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.COUNT];
3449     private static MethodHandle makeZero(Class<?> rtype) {
3450         MethodType mtype = methodType(rtype);
3451         LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
3452         return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);
3453     }




1245   MH_newProcessBuilder.invoke("x", "y", "z");
1246 assertEquals("[x, y, z]", pb.command().toString());
1247          * }</pre></blockquote>
1248          * @param refc the class or interface from which the method is accessed
1249          * @param type the type of the method, with the receiver argument omitted, and a void return type
1250          * @return the desired method handle
1251          * @throws NoSuchMethodException if the constructor does not exist
1252          * @throws IllegalAccessException if access checking fails
1253          *                                or if the method's variable arity modifier bit
1254          *                                is set and {@code asVarargsCollector} fails
1255          * @exception SecurityException if a security manager is present and it
1256          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1257          * @throws NullPointerException if any argument is null
1258          */
1259         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
1260             if (refc.isArray()) {
1261                 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
1262             }
1263             String name = "<init>";
1264             if (MinimalValueTypes_1_0.isValueType(refc)) {

1265                 //shady: The findConstructor method of Lookup will expose all accessible constructors of the original
1266                 //value-capable class, for both the Q-type and the legacy L-type. The return type of a method handle produced
1267                 //by findConstructor will be identical with the lookup class, even if it is a Q-type.
1268                 refc = MinimalValueTypes_1_0.getValueCapableClass(refc);



1269             }
1270             MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
1271             return getDirectConstructor(refc, ctor);
1272         }
1273 
1274         /**
1275          * Looks up a class by name from the lookup context defined by this {@code Lookup} object. The static
1276          * initializer of the class is not run.
1277          * <p>
1278          * The lookup context here is determined by the {@linkplain #lookupClass() lookup class}, its class
1279          * loader, and the {@linkplain #lookupModes() lookup modes}. In particular, the method first attempts to
1280          * load the requested class, and then determines whether the class is accessible to this lookup object.
1281          *
1282          * @param targetName the fully qualified name of the class to be looked up.
1283          * @return the requested class.
1284          * @exception SecurityException if a security manager is present and it
1285          *            <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1286          * @throws LinkageError if the linkage fails
1287          * @throws ClassNotFoundException if the class cannot be loaded by the lookup class' loader.
1288          * @throws IllegalAccessException if the class is not accessible, using the allowed access


1405         /**
1406          * Produces a method handle giving read access to a non-static field.
1407          * The type of the method handle will have a return type of the field's
1408          * value type.
1409          * The method handle's single argument will be the instance containing
1410          * the field.
1411          * Access checking is performed immediately on behalf of the lookup class.
1412          * @param refc the class or interface from which the method is accessed
1413          * @param name the field's name
1414          * @param type the field's type
1415          * @return a method handle which can load values from the field
1416          * @throws NoSuchFieldException if the field does not exist
1417          * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
1418          * @exception SecurityException if a security manager is present and it
1419          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
1420          * @throws NullPointerException if any argument is null
1421          * @see #findVarHandle(Class, String, Class)
1422          */
1423         public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
1424             if (MinimalValueTypes_1_0.isValueType(refc)) {

1425                 return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(refc)).findGetter(this, name, type);



1426             } else {
1427                 MemberName field = resolveOrFail(REF_getField, refc, name, type);
1428                 return getDirectField(REF_getField, refc, field);
1429             }
1430         }
1431 
1432         /**
1433          * Produces a method handle giving write access to a non-static field.
1434          * The type of the method handle will have a void return type.
1435          * The method handle will take two arguments, the instance containing
1436          * the field, and the value to be stored.
1437          * The second argument will be of the field's value type.
1438          * Access checking is performed immediately on behalf of the lookup class.
1439          * @param refc the class or interface from which the method is accessed
1440          * @param name the field's name
1441          * @param type the field's type
1442          * @return a method handle which can store values into the field
1443          * @throws NoSuchFieldException if the field does not exist
1444          * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
1445          * @exception SecurityException if a security manager is present and it


2585      * The type of the method handle will have a void return type.
2586      * Its last argument will be the array's element type.
2587      * The first and second arguments will be the array type and int.
2588      * @param arrayClass the class of an array
2589      * @return a method handle which can store values into the array type
2590      * @throws NullPointerException if the argument is null
2591      * @throws IllegalArgumentException if arrayClass is not an array type
2592      */
2593     public static
2594     MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
2595         ValueType<?> compValue = valueComponent(arrayClass);
2596         return (compValue != null) ?
2597                 compValue.arraySetter() :
2598                 MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET);
2599     }
2600 
2601     @SuppressWarnings("unchecked")
2602     private static <Z> ValueType<Z> valueComponent(Class<Z> clazz) {
2603         Class<?> comp = clazz.getComponentType();
2604         if (MinimalValueTypes_1_0.isValueType(comp)) {

2605             return (ValueType<Z>)ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(comp));



2606         } else {
2607             return null;
2608         }
2609     }
2610 
2611     /**
2612      * Produces a VarHandle giving access to elements of an array of type
2613      * {@code arrayClass}.  The VarHandle's variable type is the component type
2614      * of {@code arrayClass} and the list of coordinate types is
2615      * {@code (arrayClass, int)}, where the {@code int} coordinate type
2616      * corresponds to an argument that is an index into an array.
2617      * <p>
2618      * Certain access modes of the returned VarHandle are unsupported under
2619      * the following conditions:
2620      * <ul>
2621      * <li>if the component type is anything other than {@code byte},
2622      *     {@code short}, {@code char}, {@code int}, {@code long},
2623      *     {@code float}, or {@code double} then numeric atomic update access
2624      *     modes are unsupported.
2625      * <li>if the field type is anything other than {@code boolean},


3355      * Produces a constant method handle of the requested return type which
3356      * returns the default value for that type every time it is invoked.
3357      * The resulting constant method handle will have no side effects.
3358      * <p>The returned method handle is equivalent to {@code empty(methodType(type))}.
3359      * It is also equivalent to {@code explicitCastArguments(constant(Object.class, null), methodType(type))},
3360      * since {@code explicitCastArguments} converts {@code null} to default values.
3361      * @param type the expected return type of the desired method handle
3362      * @return a constant method handle that takes no arguments
3363      *         and returns the default value of the given type (or void, if the type is void)
3364      * @throws NullPointerException if the argument is null
3365      * @see MethodHandles#constant
3366      * @see MethodHandles#empty
3367      * @see MethodHandles#explicitCastArguments
3368      * @since 9
3369      */
3370     public static MethodHandle zero(Class<?> type) {
3371         Objects.requireNonNull(type);
3372         if (type.isPrimitive()) {
3373             return zero(Wrapper.forPrimitiveType(type), type);
3374         } else if (MinimalValueTypes_1_0.isValueType(type)) {

3375             return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(type)).defaultValueConstant();



3376         } else {
3377             return zero(Wrapper.OBJECT, type);
3378         }
3379     }
3380 
3381     private static MethodHandle identityOrVoid(Class<?> type) {
3382         return type == void.class ? zero(type) : identity(type);
3383     }
3384 
3385     /**
3386      * Produces a method handle of the requested type which ignores any arguments, does nothing,
3387      * and returns a suitable default depending on the return type.
3388      * That is, it returns a zero primitive value, a {@code null}, or {@code void}.
3389      * <p>The returned method handle is equivalent to
3390      * {@code dropArguments(zero(type.returnType()), 0, type.parameterList())}.
3391      * <p>
3392      * @apiNote Given a predicate and target, a useful "if-then" construct can be produced as
3393      * {@code guardWithTest(pred, target, empty(target.type())}.
3394      * @param type the type of the desired method handle
3395      * @return a constant method handle of the given type, which returns a default value of the given return type
3396      * @throws NullPointerException if the argument is null
3397      * @see MethodHandles#zero
3398      * @see MethodHandles#constant
3399      * @since 9
3400      */
3401     public static  MethodHandle empty(MethodType type) {
3402         Objects.requireNonNull(type);
3403         return dropArguments(zero(type.returnType()), 0, type.parameterList());
3404     }
3405 
3406     private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.COUNT];
3407     private static MethodHandle makeIdentity(Class<?> ptype) {
3408         if (!MinimalValueTypes_1_0.isValueType(ptype)) {
3409             MethodType mtype = MethodType.methodType(ptype, ptype);
3410             LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
3411             return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
3412         } else {

3413             return ValueType.forClass(MinimalValueTypes_1_0.getValueCapableClass(ptype)).identity();



3414         }
3415     }
3416 
3417     private static MethodHandle zero(Wrapper btw, Class<?> rtype) {
3418         int pos = btw.ordinal();
3419         MethodHandle zero = ZERO_MHS[pos];
3420         if (zero == null) {
3421             zero = setCachedMethodHandle(ZERO_MHS, pos, makeZero(btw.primitiveType()));
3422         }
3423         if (zero.type().returnType() == rtype)
3424             return zero;
3425         assert(btw == Wrapper.OBJECT);
3426         return makeZero(rtype);
3427     }
3428     private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.COUNT];
3429     private static MethodHandle makeZero(Class<?> rtype) {
3430         MethodType mtype = methodType(rtype);
3431         LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
3432         return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);
3433     }


< prev index next >