196 * <li>Likewise, if {@code T} or {@code MT} |
196 * <li>Likewise, if {@code T} or {@code MT} |
197 * is not symbolically accessible from the lookup class's loader, |
197 * is not symbolically accessible from the lookup class's loader, |
198 * the lookup can still succeed. |
198 * the lookup can still succeed. |
199 * For example, lookups for {@code MethodHandle.invokeExact} and |
199 * For example, lookups for {@code MethodHandle.invokeExact} and |
200 * {@code MethodHandle.invokeGeneric} will always succeed, regardless of requested type. |
200 * {@code MethodHandle.invokeGeneric} will always succeed, regardless of requested type. |
|
201 * <li>If there is a security manager installed, it can forbid the lookup |
|
202 * on various grounds (<a href="#secmgr">see below</a>). |
|
203 * By contrast, the {@code ldc} instruction is not subject to |
|
204 * security manager checks. |
201 * </ul> |
205 * </ul> |
202 * |
206 * |
203 * <h3><a name="access"></a>Access checking</h3> |
207 * <h3><a name="access"></a>Access checking</h3> |
204 * Access checks are applied in the factory methods of {@code Lookup}, |
208 * Access checks are applied in the factory methods of {@code Lookup}, |
205 * when a method handle is created. |
209 * when a method handle is created. |
253 * {@code C.E} would be unable to those private members. |
257 * {@code C.E} would be unable to those private members. |
254 * A workaround for this limitation is the {@link Lookup#in Lookup.in} method, |
258 * A workaround for this limitation is the {@link Lookup#in Lookup.in} method, |
255 * which can transform a lookup on {@code C.E} into one on any of those other |
259 * which can transform a lookup on {@code C.E} into one on any of those other |
256 * classes, without special elevation of privilege. |
260 * classes, without special elevation of privilege. |
257 * <p> |
261 * <p> |
|
262 * Although bytecode instructions can only refer to classes in |
|
263 * a related class loader, this API can search for methods in any |
|
264 * class, as long as a reference to its {@code Class} object is |
|
265 * available. Such cross-loader references are also possible with the |
|
266 * Core Reflection API, and are impossible to bytecode instructions |
|
267 * such as {@code invokestatic} or {@code getfield}. |
|
268 * There is a {@linkplain java.lang.SecurityManager security manager API} |
|
269 * to allow applications to check such cross-loader references. |
|
270 * These checks apply to both the {@code MethodHandles.Lookup} API |
|
271 * and the Core Reflection API |
|
272 * (as found on {@link java.lang.Class Class}). |
|
273 * <p> |
258 * Access checks only apply to named and reflected methods, |
274 * Access checks only apply to named and reflected methods, |
259 * constructors, and fields. |
275 * constructors, and fields. |
260 * Other method handle creation methods, such as |
276 * Other method handle creation methods, such as |
261 * {@link #convertArguments MethodHandles.convertArguments}, |
277 * {@link #convertArguments MethodHandles.convertArguments}, |
262 * do not require any access checks, and are done |
278 * do not require any access checks, and are done |
263 * with static methods of {@link MethodHandles}, |
279 * with static methods of {@link MethodHandles}, |
264 * independently of any {@code Lookup} object. |
280 * independently of any {@code Lookup} object. |
|
281 * |
|
282 * <h3>Security manager interactions</h3> |
|
283 * <a name="secmgr"></a> |
|
284 * If a security manager is present, member lookups are subject to |
|
285 * additional checks. |
|
286 * From one to four calls are made to the security manager. |
|
287 * Any of these calls can refuse access by throwing a |
|
288 * {@link java.lang.SecurityException SecurityException}. |
|
289 * Define {@code smgr} as the security manager, |
|
290 * {@code refc} as the containing class in which the member |
|
291 * is being sought, and {@code defc} as the class in which the |
|
292 * member is actually defined. |
|
293 * The calls are made according to the following rules: |
|
294 * <ul> |
|
295 * <li>In all cases, {@link SecurityManager#checkMemberAccess |
|
296 * smgr.checkMemberAccess(refc, Member.PUBLIC)} is called. |
|
297 * <li>If the class loader of the lookup class is not |
|
298 * the same as or an ancestor of the class loader of {@code refc}, |
|
299 * then {@link SecurityManager#checkPackageAccess |
|
300 * smgr.checkPackageAccess(refcPkg)} is called, |
|
301 * where {@code refcPkg} is the package of {@code refc}. |
|
302 * <li>If the retrieved member is not public, |
|
303 * {@link SecurityManager#checkMemberAccess |
|
304 * smgr.checkMemberAccess(defc, Member.DECLARED)} is called. |
|
305 * (Note that {@code defc} might be the same as {@code refc}.) |
|
306 * <li>If the retrieved member is not public, |
|
307 * and if {@code defc} and {@code refc} are in different class loaders, |
|
308 * and if the class loader of the lookup class is not |
|
309 * the same as or an ancestor of the class loader of {@code defc}, |
|
310 * then {@link SecurityManager#checkPackageAccess |
|
311 * smgr.checkPackageAccess(defcPkg)} is called, |
|
312 * where {@code defcPkg} is the package of {@code defc}. |
|
313 * </ul> |
|
314 * In all cases, the requesting class presented to the security |
|
315 * manager will be the lookup class from the current {@code Lookup} object. |
265 */ |
316 */ |
266 public static final |
317 public static final |
267 class Lookup { |
318 class Lookup { |
268 /** The class on behalf of whom the lookup is being performed. */ |
319 /** The class on behalf of whom the lookup is being performed. */ |
269 private final Class<?> lookupClass; |
320 private final Class<?> lookupClass; |
516 * @param name the name of the method |
567 * @param name the name of the method |
517 * @param type the type of the method |
568 * @param type the type of the method |
518 * @return the desired method handle |
569 * @return the desired method handle |
519 * @throws NoSuchMethodException if the method does not exist |
570 * @throws NoSuchMethodException if the method does not exist |
520 * @throws IllegalAccessException if access checking fails, or if the method is not {@code static} |
571 * @throws IllegalAccessException if access checking fails, or if the method is not {@code static} |
|
572 * @exception SecurityException if a security manager is present and it |
|
573 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
521 * @throws NullPointerException if any argument is null |
574 * @throws NullPointerException if any argument is null |
522 */ |
575 */ |
523 public |
576 public |
524 MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
577 MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
525 MemberName method = resolveOrFail(refc, name, type, true); |
578 MemberName method = resolveOrFail(refc, name, type, true); |
556 * @param name the name of the method |
609 * @param name the name of the method |
557 * @param type the type of the method, with the receiver argument omitted |
610 * @param type the type of the method, with the receiver argument omitted |
558 * @return the desired method handle |
611 * @return the desired method handle |
559 * @throws NoSuchMethodException if the method does not exist |
612 * @throws NoSuchMethodException if the method does not exist |
560 * @throws IllegalAccessException if access checking fails, or if the method is {@code static} |
613 * @throws IllegalAccessException if access checking fails, or if the method is {@code static} |
|
614 * @exception SecurityException if a security manager is present and it |
|
615 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
561 * @throws NullPointerException if any argument is null |
616 * @throws NullPointerException if any argument is null |
562 */ |
617 */ |
563 public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
618 public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
564 MemberName method = resolveOrFail(refc, name, type, false); |
619 MemberName method = resolveOrFail(refc, name, type, false); |
565 checkMethod(refc, method, false); |
620 checkMethod(refc, method, false); |
585 * @param refc the class or interface from which the method is accessed |
640 * @param refc the class or interface from which the method is accessed |
586 * @param type the type of the method, with the receiver argument omitted, and a void return type |
641 * @param type the type of the method, with the receiver argument omitted, and a void return type |
587 * @return the desired method handle |
642 * @return the desired method handle |
588 * @throws NoSuchMethodException if the constructor does not exist |
643 * @throws NoSuchMethodException if the constructor does not exist |
589 * @throws IllegalAccessException if access checking fails |
644 * @throws IllegalAccessException if access checking fails |
|
645 * @exception SecurityException if a security manager is present and it |
|
646 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
590 * @throws NullPointerException if any argument is null |
647 * @throws NullPointerException if any argument is null |
591 */ |
648 */ |
592 public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
649 public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
593 String name = "<init>"; |
650 String name = "<init>"; |
594 MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull()); |
651 MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull()); |
640 * @param type the type of the method, with the receiver argument omitted |
697 * @param type the type of the method, with the receiver argument omitted |
641 * @param specialCaller the proposed calling class to perform the {@code invokespecial} |
698 * @param specialCaller the proposed calling class to perform the {@code invokespecial} |
642 * @return the desired method handle |
699 * @return the desired method handle |
643 * @throws NoSuchMethodException if the method does not exist |
700 * @throws NoSuchMethodException if the method does not exist |
644 * @throws IllegalAccessException if access checking fails |
701 * @throws IllegalAccessException if access checking fails |
|
702 * @exception SecurityException if a security manager is present and it |
|
703 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
645 * @throws NullPointerException if any argument is null |
704 * @throws NullPointerException if any argument is null |
646 */ |
705 */ |
647 public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, |
706 public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, |
648 Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { |
707 Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { |
649 checkSpecialCaller(specialCaller); |
708 checkSpecialCaller(specialCaller); |
664 * @param name the field's name |
723 * @param name the field's name |
665 * @param type the field's type |
724 * @param type the field's type |
666 * @return a method handle which can load values from the field |
725 * @return a method handle which can load values from the field |
667 * @throws NoSuchFieldException if the field does not exist |
726 * @throws NoSuchFieldException if the field does not exist |
668 * @throws IllegalAccessException if access checking fails, or if the field is {@code static} |
727 * @throws IllegalAccessException if access checking fails, or if the field is {@code static} |
|
728 * @exception SecurityException if a security manager is present and it |
|
729 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
669 * @throws NullPointerException if any argument is null |
730 * @throws NullPointerException if any argument is null |
670 */ |
731 */ |
671 public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
732 public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
672 return makeAccessor(refc, name, type, false, false); |
733 return makeAccessor(refc, name, type, false, false); |
673 } |
734 } |
683 * @param name the field's name |
744 * @param name the field's name |
684 * @param type the field's type |
745 * @param type the field's type |
685 * @return a method handle which can store values into the field |
746 * @return a method handle which can store values into the field |
686 * @throws NoSuchFieldException if the field does not exist |
747 * @throws NoSuchFieldException if the field does not exist |
687 * @throws IllegalAccessException if access checking fails, or if the field is {@code static} |
748 * @throws IllegalAccessException if access checking fails, or if the field is {@code static} |
|
749 * @exception SecurityException if a security manager is present and it |
|
750 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
688 * @throws NullPointerException if any argument is null |
751 * @throws NullPointerException if any argument is null |
689 */ |
752 */ |
690 public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
753 public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
691 return makeAccessor(refc, name, type, false, true); |
754 return makeAccessor(refc, name, type, false, true); |
692 } |
755 } |
701 * @param name the field's name |
764 * @param name the field's name |
702 * @param type the field's type |
765 * @param type the field's type |
703 * @return a method handle which can load values from the field |
766 * @return a method handle which can load values from the field |
704 * @throws NoSuchFieldException if the field does not exist |
767 * @throws NoSuchFieldException if the field does not exist |
705 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} |
768 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} |
|
769 * @exception SecurityException if a security manager is present and it |
|
770 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
706 * @throws NullPointerException if any argument is null |
771 * @throws NullPointerException if any argument is null |
707 */ |
772 */ |
708 public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
773 public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
709 return makeAccessor(refc, name, type, true, false); |
774 return makeAccessor(refc, name, type, true, false); |
710 } |
775 } |
719 * @param name the field's name |
784 * @param name the field's name |
720 * @param type the field's type |
785 * @param type the field's type |
721 * @return a method handle which can store values into the field |
786 * @return a method handle which can store values into the field |
722 * @throws NoSuchFieldException if the field does not exist |
787 * @throws NoSuchFieldException if the field does not exist |
723 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} |
788 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} |
|
789 * @exception SecurityException if a security manager is present and it |
|
790 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
724 * @throws NullPointerException if any argument is null |
791 * @throws NullPointerException if any argument is null |
725 */ |
792 */ |
726 public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
793 public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
727 return makeAccessor(refc, name, type, true, true); |
794 return makeAccessor(refc, name, type, true, true); |
728 } |
795 } |
762 * @param name the name of the method |
829 * @param name the name of the method |
763 * @param type the type of the method, with the receiver argument omitted |
830 * @param type the type of the method, with the receiver argument omitted |
764 * @return the desired method handle |
831 * @return the desired method handle |
765 * @throws NoSuchMethodException if the method does not exist |
832 * @throws NoSuchMethodException if the method does not exist |
766 * @throws IllegalAccessException if access checking fails |
833 * @throws IllegalAccessException if access checking fails |
|
834 * @exception SecurityException if a security manager is present and it |
|
835 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
767 * @throws NullPointerException if any argument is null |
836 * @throws NullPointerException if any argument is null |
768 */ |
837 */ |
769 public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
838 public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
770 Class<? extends Object> refc = receiver.getClass(); // may get NPE |
839 Class<? extends Object> refc = receiver.getClass(); // may get NPE |
771 MemberName method = resolveOrFail(refc, name, type, false); |
840 MemberName method = resolveOrFail(refc, name, type, false); |