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 } |