24 */ |
24 */ |
25 |
25 |
26 package java.lang.invoke; |
26 package java.lang.invoke; |
27 |
27 |
28 import java.lang.reflect.*; |
28 import java.lang.reflect.*; |
|
29 import java.security.AccessController; |
|
30 import java.security.PrivilegedAction; |
|
31 import java.util.List; |
|
32 import java.util.ArrayList; |
|
33 import java.util.Arrays; |
29 import sun.invoke.util.ValueConversions; |
34 import sun.invoke.util.ValueConversions; |
30 import sun.invoke.util.VerifyAccess; |
35 import sun.invoke.util.VerifyAccess; |
31 import sun.invoke.util.Wrapper; |
36 import sun.invoke.util.Wrapper; |
32 import java.util.List; |
37 import sun.reflect.CallerSensitive; |
33 import java.util.ArrayList; |
|
34 import java.util.Arrays; |
|
35 import sun.reflect.Reflection; |
38 import sun.reflect.Reflection; |
|
39 import sun.security.util.SecurityConstants; |
36 import static java.lang.invoke.MethodHandleStatics.*; |
40 import static java.lang.invoke.MethodHandleStatics.*; |
37 import static java.lang.invoke.MethodHandleNatives.Constants.*; |
41 import static java.lang.invoke.MethodHandleNatives.Constants.*; |
38 |
42 |
39 /** |
43 /** |
40 * This class consists exclusively of static methods that operate on or return |
44 * This class consists exclusively of static methods that operate on or return |
414 |
419 |
415 /** Embody the current class (the lookupClass) as a lookup class |
420 /** Embody the current class (the lookupClass) as a lookup class |
416 * for method handle creation. |
421 * for method handle creation. |
417 * Must be called by from a method in this package, |
422 * Must be called by from a method in this package, |
418 * which in turn is called by a method not in this package. |
423 * which in turn is called by a method not in this package. |
419 * <p> |
424 */ |
420 * Also, don't make it private, lest javac interpose |
425 Lookup(Class<?> lookupClass) { |
421 * an access$N method. |
426 this(lookupClass, ALL_MODES); |
422 */ |
|
423 Lookup() { |
|
424 this(getCallerClassAtEntryPoint(false), ALL_MODES); |
|
425 // make sure we haven't accidentally picked up a privileged class: |
427 // make sure we haven't accidentally picked up a privileged class: |
426 checkUnprivilegedlookupClass(lookupClass); |
428 checkUnprivilegedlookupClass(lookupClass); |
427 } |
|
428 |
|
429 Lookup(Class<?> lookupClass) { |
|
430 this(lookupClass, ALL_MODES); |
|
431 } |
429 } |
432 |
430 |
433 private Lookup(Class<?> lookupClass, int allowedModes) { |
431 private Lookup(Class<?> lookupClass, int allowedModes) { |
434 this.lookupClass = lookupClass; |
432 this.lookupClass = lookupClass; |
435 this.allowedModes = allowedModes; |
433 this.allowedModes = allowedModes; |
552 assert(false) : cname; |
550 assert(false) : cname; |
553 return cname; |
551 return cname; |
554 } |
552 } |
555 } |
553 } |
556 |
554 |
557 /* Obtain the external caller class, when called from Lookup.<init> or a first-level subroutine. */ |
|
558 private static Class<?> getCallerClassAtEntryPoint(boolean inSubroutine) { |
|
559 final int CALLER_DEPTH = 4; |
|
560 // Stack for the constructor entry point (inSubroutine=false): |
|
561 // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint, |
|
562 // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller |
|
563 // The stack is slightly different for a subroutine of a Lookup.find* method: |
|
564 // 2: Lookup.*, 3: Lookup.find*.*, 4: caller |
|
565 // Note: This should be the only use of getCallerClass in this file. |
|
566 assert(Reflection.getCallerClass(CALLER_DEPTH-2) == Lookup.class); |
|
567 assert(Reflection.getCallerClass(CALLER_DEPTH-1) == (inSubroutine ? Lookup.class : MethodHandles.class)); |
|
568 return Reflection.getCallerClass(CALLER_DEPTH); |
|
569 } |
|
570 |
|
571 /** |
555 /** |
572 * Produces a method handle for a static method. |
556 * Produces a method handle for a static method. |
573 * The type of the method handle will be that of the method. |
557 * The type of the method handle will be that of the method. |
574 * (Since static methods do not take receivers, there is no |
558 * (Since static methods do not take receivers, there is no |
575 * additional receiver argument inserted into the method handle type, |
559 * additional receiver argument inserted into the method handle type, |
592 * is set and {@code asVarargsCollector} fails |
576 * is set and {@code asVarargsCollector} fails |
593 * @exception SecurityException if a security manager is present and it |
577 * @exception SecurityException if a security manager is present and it |
594 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
578 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
595 * @throws NullPointerException if any argument is null |
579 * @throws NullPointerException if any argument is null |
596 */ |
580 */ |
|
581 @CallerSensitive |
597 public |
582 public |
598 MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
583 MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
599 MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); |
584 MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); |
600 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
585 Class<?> callerClass = Reflection.getCallerClass(); |
601 Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor |
586 checkSecurityManager(refc, method, callerClass); |
602 return getDirectMethod(REF_invokeStatic, refc, method, callerClass); |
587 return getDirectMethod(REF_invokeStatic, refc, method, |
|
588 findBoundCallerClass(method, callerClass)); |
603 } |
589 } |
604 |
590 |
605 /** |
591 /** |
606 * Produces a method handle for a virtual method. |
592 * Produces a method handle for a virtual method. |
607 * The type of the method handle will be that of the method, |
593 * The type of the method handle will be that of the method, |
643 * is set and {@code asVarargsCollector} fails |
629 * is set and {@code asVarargsCollector} fails |
644 * @exception SecurityException if a security manager is present and it |
630 * @exception SecurityException if a security manager is present and it |
645 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
631 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
646 * @throws NullPointerException if any argument is null |
632 * @throws NullPointerException if any argument is null |
647 */ |
633 */ |
|
634 @CallerSensitive |
648 public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
635 public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
649 if (refc == MethodHandle.class) { |
636 if (refc == MethodHandle.class) { |
650 MethodHandle mh = findVirtualForMH(name, type); |
637 MethodHandle mh = findVirtualForMH(name, type); |
651 if (mh != null) return mh; |
638 if (mh != null) return mh; |
652 } |
639 } |
653 byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); |
640 byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); |
654 MemberName method = resolveOrFail(refKind, refc, name, type); |
641 MemberName method = resolveOrFail(refKind, refc, name, type); |
655 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
642 Class<?> callerClass = Reflection.getCallerClass(); |
656 Class<?> callerClass = findBoundCallerClass(method); |
643 checkSecurityManager(refc, method, callerClass); |
657 return getDirectMethod(refKind, refc, method, callerClass); |
644 return getDirectMethod(refKind, refc, method, |
|
645 findBoundCallerClass(method, callerClass)); |
658 } |
646 } |
659 private MethodHandle findVirtualForMH(String name, MethodType type) { |
647 private MethodHandle findVirtualForMH(String name, MethodType type) { |
660 // these names require special lookups because of the implicit MethodType argument |
648 // these names require special lookups because of the implicit MethodType argument |
661 if ("invoke".equals(name)) |
649 if ("invoke".equals(name)) |
662 return invoker(type); |
650 return invoker(type); |
689 * is set and {@code asVarargsCollector} fails |
677 * is set and {@code asVarargsCollector} fails |
690 * @exception SecurityException if a security manager is present and it |
678 * @exception SecurityException if a security manager is present and it |
691 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
679 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
692 * @throws NullPointerException if any argument is null |
680 * @throws NullPointerException if any argument is null |
693 */ |
681 */ |
|
682 @CallerSensitive |
694 public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
683 public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
695 String name = "<init>"; |
684 String name = "<init>"; |
696 MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type); |
685 MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type); |
697 checkSecurityManager(refc, ctor); // stack walk magic: do not refactor |
686 checkSecurityManager(refc, ctor, Reflection.getCallerClass()); |
698 return getDirectConstructor(refc, ctor); |
687 return getDirectConstructor(refc, ctor); |
699 } |
688 } |
700 |
689 |
701 /** |
690 /** |
702 * Produces an early-bound method handle for a virtual method, |
691 * Produces an early-bound method handle for a virtual method, |
730 * is set and {@code asVarargsCollector} fails |
719 * is set and {@code asVarargsCollector} fails |
731 * @exception SecurityException if a security manager is present and it |
720 * @exception SecurityException if a security manager is present and it |
732 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
721 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
733 * @throws NullPointerException if any argument is null |
722 * @throws NullPointerException if any argument is null |
734 */ |
723 */ |
|
724 @CallerSensitive |
735 public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, |
725 public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, |
736 Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { |
726 Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { |
737 checkSpecialCaller(specialCaller); |
727 checkSpecialCaller(specialCaller); |
738 Lookup specialLookup = this.in(specialCaller); |
728 Lookup specialLookup = this.in(specialCaller); |
739 MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); |
729 MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); |
740 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
730 Class<?> callerClass = Reflection.getCallerClass(); |
741 Class<?> callerClass = findBoundCallerClass(method); |
731 checkSecurityManager(refc, method, callerClass); |
742 return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, callerClass); |
732 return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, |
|
733 findBoundCallerClass(method, callerClass)); |
743 } |
734 } |
744 |
735 |
745 /** |
736 /** |
746 * Produces a method handle giving read access to a non-static field. |
737 * Produces a method handle giving read access to a non-static field. |
747 * The type of the method handle will have a return type of the field's |
738 * The type of the method handle will have a return type of the field's |
757 * @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} |
758 * @exception SecurityException if a security manager is present and it |
749 * @exception SecurityException if a security manager is present and it |
759 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
750 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
760 * @throws NullPointerException if any argument is null |
751 * @throws NullPointerException if any argument is null |
761 */ |
752 */ |
|
753 @CallerSensitive |
762 public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
754 public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
763 MemberName field = resolveOrFail(REF_getField, refc, name, type); |
755 MemberName field = resolveOrFail(REF_getField, refc, name, type); |
764 checkSecurityManager(refc, field); // stack walk magic: do not refactor |
756 checkSecurityManager(refc, field, Reflection.getCallerClass()); |
765 return getDirectField(REF_getField, refc, field); |
757 return getDirectField(REF_getField, refc, field); |
766 } |
758 } |
767 |
759 |
768 /** |
760 /** |
769 * Produces a method handle giving write access to a non-static field. |
761 * Produces a method handle giving write access to a non-static field. |
780 * @throws IllegalAccessException if access checking fails, or if the field is {@code static} |
772 * @throws IllegalAccessException if access checking fails, or if the field is {@code static} |
781 * @exception SecurityException if a security manager is present and it |
773 * @exception SecurityException if a security manager is present and it |
782 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
774 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
783 * @throws NullPointerException if any argument is null |
775 * @throws NullPointerException if any argument is null |
784 */ |
776 */ |
|
777 @CallerSensitive |
785 public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
778 public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
786 MemberName field = resolveOrFail(REF_putField, refc, name, type); |
779 MemberName field = resolveOrFail(REF_putField, refc, name, type); |
787 checkSecurityManager(refc, field); // stack walk magic: do not refactor |
780 checkSecurityManager(refc, field, Reflection.getCallerClass()); |
788 return getDirectField(REF_putField, refc, field); |
781 return getDirectField(REF_putField, refc, field); |
789 } |
782 } |
790 |
783 |
791 /** |
784 /** |
792 * Produces a method handle giving read access to a static field. |
785 * Produces a method handle giving read access to a static field. |
802 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} |
795 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} |
803 * @exception SecurityException if a security manager is present and it |
796 * @exception SecurityException if a security manager is present and it |
804 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
797 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
805 * @throws NullPointerException if any argument is null |
798 * @throws NullPointerException if any argument is null |
806 */ |
799 */ |
|
800 @CallerSensitive |
807 public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
801 public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
808 MemberName field = resolveOrFail(REF_getStatic, refc, name, type); |
802 MemberName field = resolveOrFail(REF_getStatic, refc, name, type); |
809 checkSecurityManager(refc, field); // stack walk magic: do not refactor |
803 checkSecurityManager(refc, field, Reflection.getCallerClass()); |
810 return getDirectField(REF_getStatic, refc, field); |
804 return getDirectField(REF_getStatic, refc, field); |
811 } |
805 } |
812 |
806 |
813 /** |
807 /** |
814 * Produces a method handle giving write access to a static field. |
808 * Produces a method handle giving write access to a static field. |
824 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} |
818 * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} |
825 * @exception SecurityException if a security manager is present and it |
819 * @exception SecurityException if a security manager is present and it |
826 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
820 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
827 * @throws NullPointerException if any argument is null |
821 * @throws NullPointerException if any argument is null |
828 */ |
822 */ |
|
823 @CallerSensitive |
829 public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
824 public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { |
830 MemberName field = resolveOrFail(REF_putStatic, refc, name, type); |
825 MemberName field = resolveOrFail(REF_putStatic, refc, name, type); |
831 checkSecurityManager(refc, field); // stack walk magic: do not refactor |
826 checkSecurityManager(refc, field, Reflection.getCallerClass()); |
832 return getDirectField(REF_putStatic, refc, field); |
827 return getDirectField(REF_putStatic, refc, field); |
833 } |
828 } |
834 |
829 |
835 /** |
830 /** |
836 * Produces an early-bound method handle for a non-static method. |
831 * Produces an early-bound method handle for a non-static method. |
876 * is set and {@code asVarargsCollector} fails |
871 * is set and {@code asVarargsCollector} fails |
877 * @exception SecurityException if a security manager is present and it |
872 * @exception SecurityException if a security manager is present and it |
878 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
873 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> |
879 * @throws NullPointerException if any argument is null |
874 * @throws NullPointerException if any argument is null |
880 */ |
875 */ |
|
876 @CallerSensitive |
881 public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
877 public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { |
882 Class<? extends Object> refc = receiver.getClass(); // may get NPE |
878 Class<? extends Object> refc = receiver.getClass(); // may get NPE |
883 MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); |
879 MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); |
884 checkSecurityManager(refc, method); // stack walk magic: do not refactor |
880 Class<?> callerClass = Reflection.getCallerClass(); |
885 Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor |
881 checkSecurityManager(refc, method, callerClass); |
886 MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, callerClass); |
882 MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, |
|
883 findBoundCallerClass(method, callerClass)); |
887 return mh.bindReceiver(receiver).setVarargs(method); |
884 return mh.bindReceiver(receiver).setVarargs(method); |
888 } |
885 } |
889 |
886 |
890 /** |
887 /** |
891 * Makes a direct method handle to <i>m</i>, if the lookup class has permission. |
888 * Makes a direct method handle to <i>m</i>, if the lookup class has permission. |
906 * @throws IllegalAccessException if access checking fails |
903 * @throws IllegalAccessException if access checking fails |
907 * or if the method's variable arity modifier bit |
904 * or if the method's variable arity modifier bit |
908 * is set and {@code asVarargsCollector} fails |
905 * is set and {@code asVarargsCollector} fails |
909 * @throws NullPointerException if the argument is null |
906 * @throws NullPointerException if the argument is null |
910 */ |
907 */ |
|
908 @CallerSensitive |
911 public MethodHandle unreflect(Method m) throws IllegalAccessException { |
909 public MethodHandle unreflect(Method m) throws IllegalAccessException { |
912 MemberName method = new MemberName(m); |
910 MemberName method = new MemberName(m); |
913 byte refKind = method.getReferenceKind(); |
911 byte refKind = method.getReferenceKind(); |
914 if (refKind == REF_invokeSpecial) |
912 if (refKind == REF_invokeSpecial) |
915 refKind = REF_invokeVirtual; |
913 refKind = REF_invokeVirtual; |
916 assert(method.isMethod()); |
914 assert(method.isMethod()); |
917 Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor |
915 Class<?> callerClass = findBoundCallerClass(method, Reflection.getCallerClass()); |
918 Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; |
916 Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; |
919 return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass); |
917 return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass); |
920 } |
918 } |
921 |
919 |
922 /** |
920 /** |
938 * @throws IllegalAccessException if access checking fails |
936 * @throws IllegalAccessException if access checking fails |
939 * or if the method's variable arity modifier bit |
937 * or if the method's variable arity modifier bit |
940 * is set and {@code asVarargsCollector} fails |
938 * is set and {@code asVarargsCollector} fails |
941 * @throws NullPointerException if any argument is null |
939 * @throws NullPointerException if any argument is null |
942 */ |
940 */ |
|
941 @CallerSensitive |
943 public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { |
942 public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { |
944 checkSpecialCaller(specialCaller); |
943 checkSpecialCaller(specialCaller); |
945 Lookup specialLookup = this.in(specialCaller); |
944 Lookup specialLookup = this.in(specialCaller); |
946 MemberName method = new MemberName(m, true); |
945 MemberName method = new MemberName(m, true); |
947 assert(method.isMethod()); |
946 assert(method.isMethod()); |
948 Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor |
947 Class<?> callerClass = findBoundCallerClass(method, Reflection.getCallerClass()); |
949 // ignore m.isAccessible: this is a new kind of access |
948 // ignore m.isAccessible: this is a new kind of access |
950 return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass); |
949 return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass); |
951 } |
950 } |
952 |
951 |
953 /** |
952 /** |
1048 /** |
1047 /** |
1049 * Find my trustable caller class if m is a caller sensitive method. |
1048 * Find my trustable caller class if m is a caller sensitive method. |
1050 * If this lookup object has private access, then the caller class is the lookupClass. |
1049 * If this lookup object has private access, then the caller class is the lookupClass. |
1051 * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). |
1050 * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). |
1052 * This is the same caller class as is used by checkSecurityManager. |
1051 * This is the same caller class as is used by checkSecurityManager. |
1053 * This function performs stack walk magic: do not refactor it. |
1052 */ |
1054 */ |
1053 Class<?> findBoundCallerClass(MemberName m, Class<?> callerAtEntryPoint) { |
1055 Class<?> findBoundCallerClass(MemberName m) { |
|
1056 Class<?> callerClass = null; |
1054 Class<?> callerClass = null; |
1057 if (MethodHandleNatives.isCallerSensitive(m)) { |
1055 if (MethodHandleNatives.isCallerSensitive(m)) { |
1058 // Do not refactor this to a more "logical" place, since it is stack walk magic. |
1056 // Do not refactor this to a more "logical" place, since it is stack walk magic. |
1059 // Note that this is the same expression as in Step 2 below in checkSecurityManager. |
1057 // Note that this is the same expression as in Step 2 below in checkSecurityManager. |
1060 callerClass = ((allowedModes & PRIVATE) != 0 |
1058 callerClass = ((allowedModes & PRIVATE) != 0 |
1061 ? lookupClass // for strong access modes, no extra check |
1059 ? lookupClass // for strong access modes, no extra check |
1062 // next line does stack walk magic; do not refactor: |
1060 : callerAtEntryPoint); |
1063 : getCallerClassAtEntryPoint(true)); |
|
1064 } |
1061 } |
1065 return callerClass; |
1062 return callerClass; |
1066 } |
1063 } |
|
1064 |
|
1065 /** |
|
1066 * Determine whether a security manager has an overridden |
|
1067 * SecurityManager.checkMemberAccess method. |
|
1068 */ |
|
1069 private boolean isCheckMemberAccessOverridden(SecurityManager sm) { |
|
1070 final Class<? extends SecurityManager> cls = sm.getClass(); |
|
1071 if (cls == SecurityManager.class) return false; |
|
1072 |
|
1073 try { |
|
1074 return cls.getMethod("checkMemberAccess", Class.class, int.class). |
|
1075 getDeclaringClass() != SecurityManager.class; |
|
1076 } catch (NoSuchMethodException e) { |
|
1077 throw new InternalError("should not reach here"); |
|
1078 } |
|
1079 } |
|
1080 |
1067 /** |
1081 /** |
1068 * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>. |
1082 * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>. |
1069 * Determines a trustable caller class to compare with refc, the symbolic reference class. |
1083 * Determines a trustable caller class to compare with refc, the symbolic reference class. |
1070 * If this lookup object has private access, then the caller class is the lookupClass. |
1084 * If this lookup object has private access, then the caller class is the lookupClass. |
1071 * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). |
1085 * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). |
1072 * This function performs stack walk magic: do not refactor it. |
1086 * This function performs stack walk magic: do not refactor it. |
1073 */ |
1087 */ |
1074 void checkSecurityManager(Class<?> refc, MemberName m) { |
1088 void checkSecurityManager(Class<?> refc, MemberName m, Class<?> caller) { |
1075 SecurityManager smgr = System.getSecurityManager(); |
1089 SecurityManager smgr = System.getSecurityManager(); |
1076 if (smgr == null) return; |
1090 if (smgr == null) return; |
1077 if (allowedModes == TRUSTED) return; |
1091 if (allowedModes == TRUSTED) return; |
|
1092 |
|
1093 final boolean overridden = isCheckMemberAccessOverridden(smgr); |
1078 // Step 1: |
1094 // Step 1: |
1079 smgr.checkMemberAccess(refc, Member.PUBLIC); |
1095 { |
|
1096 // Default policy is to allow Member.PUBLIC; no need to check |
|
1097 // permission if SecurityManager is the default implementation |
|
1098 final int which = Member.PUBLIC; |
|
1099 final Class<?> clazz = refc; |
|
1100 if (overridden) { |
|
1101 // Don't refactor; otherwise break the stack depth for |
|
1102 // checkMemberAccess of subclasses of SecurityManager as specified. |
|
1103 smgr.checkMemberAccess(clazz, which); |
|
1104 } |
|
1105 } |
|
1106 |
1080 // Step 2: |
1107 // Step 2: |
1081 Class<?> callerClass = ((allowedModes & PRIVATE) != 0 |
1108 Class<?> callerClass = ((allowedModes & PRIVATE) != 0 |
1082 ? lookupClass // for strong access modes, no extra check |
1109 ? lookupClass // for strong access modes, no extra check |
1083 // next line does stack walk magic; do not refactor: |
1110 : caller); |
1084 : getCallerClassAtEntryPoint(true)); |
|
1085 if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) || |
1111 if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) || |
1086 (callerClass != lookupClass && |
1112 (callerClass != lookupClass && |
1087 !VerifyAccess.classLoaderIsAncestor(callerClass, refc))) |
1113 !VerifyAccess.classLoaderIsAncestor(callerClass, refc))) |
1088 smgr.checkPackageAccess(VerifyAccess.getPackageName(refc)); |
1114 smgr.checkPackageAccess(VerifyAccess.getPackageName(refc)); |
|
1115 |
1089 // Step 3: |
1116 // Step 3: |
1090 if (m.isPublic()) return; |
1117 if (m.isPublic()) return; |
1091 Class<?> defc = m.getDeclaringClass(); |
1118 Class<?> defc = m.getDeclaringClass(); |
1092 smgr.checkMemberAccess(defc, Member.DECLARED); // STACK WALK HERE |
1119 { |
|
1120 // Inline SecurityManager.checkMemberAccess |
|
1121 final int which = Member.DECLARED; |
|
1122 final Class<?> clazz = defc; |
|
1123 if (!overridden) { |
|
1124 if (caller.getClassLoader() != clazz.getClassLoader()) { |
|
1125 smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); |
|
1126 } |
|
1127 } else { |
|
1128 // Don't refactor; otherwise break the stack depth for |
|
1129 // checkMemberAccess of subclasses of SecurityManager as specified. |
|
1130 smgr.checkMemberAccess(clazz, which); |
|
1131 } |
|
1132 } |
|
1133 |
1093 // Step 4: |
1134 // Step 4: |
1094 if (defc != refc) |
1135 if (defc != refc) |
1095 smgr.checkPackageAccess(VerifyAccess.getPackageName(defc)); |
1136 smgr.checkPackageAccess(VerifyAccess.getPackageName(defc)); |
1096 |
|
1097 // Comment from SM.checkMemberAccess, where which=DECLARED: |
|
1098 /* |
|
1099 * stack depth of 4 should be the caller of one of the |
|
1100 * methods in java.lang.Class that invoke checkMember |
|
1101 * access. The stack should look like: |
|
1102 * |
|
1103 * someCaller [3] |
|
1104 * java.lang.Class.someReflectionAPI [2] |
|
1105 * java.lang.Class.checkMemberAccess [1] |
|
1106 * SecurityManager.checkMemberAccess [0] |
|
1107 * |
|
1108 */ |
|
1109 // For us it is this stack: |
|
1110 // someCaller [3] |
|
1111 // Lookup.findSomeMember [2] |
|
1112 // Lookup.checkSecurityManager [1] |
|
1113 // SecurityManager.checkMemberAccess [0] |
|
1114 } |
1137 } |
1115 |
1138 |
1116 void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException { |
1139 void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException { |
1117 boolean wantStatic = (refKind == REF_invokeStatic); |
1140 boolean wantStatic = (refKind == REF_invokeStatic); |
1118 String message; |
1141 String message; |