23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package java.lang.invoke; |
26 package java.lang.invoke; |
27 |
27 |
28 import jdk.internal.org.objectweb.asm.ClassWriter; |
|
29 import jdk.internal.org.objectweb.asm.Opcodes; |
|
30 import jdk.internal.reflect.CallerSensitive; |
28 import jdk.internal.reflect.CallerSensitive; |
31 import jdk.internal.reflect.Reflection; |
29 import jdk.internal.reflect.Reflection; |
32 import jdk.internal.vm.annotation.ForceInline; |
30 import jdk.internal.vm.annotation.ForceInline; |
33 import sun.invoke.util.ValueConversions; |
31 import sun.invoke.util.ValueConversions; |
34 import sun.invoke.util.VerifyAccess; |
32 import sun.invoke.util.VerifyAccess; |
109 return new Lookup(Reflection.getCallerClass()); |
107 return new Lookup(Reflection.getCallerClass()); |
110 } |
108 } |
111 |
109 |
112 /** |
110 /** |
113 * Returns a {@link Lookup lookup object} which is trusted minimally. |
111 * Returns a {@link Lookup lookup object} which is trusted minimally. |
114 * It can only be used to create method handles to public members in |
112 * The lookup has the {@code PUBLIC} and {@code UNCONDITIONAL} modes. |
|
113 * It can only be used to create method handles to public members of |
115 * public classes in packages that are exported unconditionally. |
114 * public classes in packages that are exported unconditionally. |
116 * <p> |
115 * <p> |
117 * For now, the {@linkplain Lookup#lookupClass lookup class} of this lookup |
116 * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class} |
118 * object is in an unnamed module. |
117 * of this lookup object will be {@link java.lang.Object}. |
119 * Consequently, the lookup context of this lookup object will be the bootstrap |
118 * |
120 * class loader, which means it cannot find user classes. |
119 * @apiNote The use of Object is conventional, and because the lookup modes are |
|
120 * limited, there is no special access provided to the internals of Object, its package |
|
121 * or its module. Consequently, the lookup context of this lookup object will be the |
|
122 * bootstrap class loader, which means it cannot find user classes. |
121 * |
123 * |
122 * <p style="font-size:smaller;"> |
124 * <p style="font-size:smaller;"> |
123 * <em>Discussion:</em> |
125 * <em>Discussion:</em> |
124 * The lookup class can be changed to any other class {@code C} using an expression of the form |
126 * The lookup class can be changed to any other class {@code C} using an expression of the form |
125 * {@link Lookup#in publicLookup().in(C.class)}. |
127 * {@link Lookup#in publicLookup().in(C.class)}. |
127 * A public lookup object is always subject to |
129 * A public lookup object is always subject to |
128 * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>. |
130 * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>. |
129 * Also, it cannot access |
131 * Also, it cannot access |
130 * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>. |
132 * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>. |
131 * @return a lookup object which is trusted minimally |
133 * @return a lookup object which is trusted minimally |
|
134 * |
|
135 * @revised 9 |
|
136 * @spec JPMS |
132 */ |
137 */ |
133 public static Lookup publicLookup() { |
138 public static Lookup publicLookup() { |
134 // During VM startup then only classes in the java.base module can be |
139 return Lookup.PUBLIC_LOOKUP; |
135 // loaded and linked. This is because java.base exports aren't setup until |
|
136 // the module system is initialized, hence types in the unnamed module |
|
137 // (or any named module) can't link to java/lang/Object. |
|
138 if (!jdk.internal.misc.VM.isModuleSystemInited()) { |
|
139 return new Lookup(Object.class, Lookup.PUBLIC); |
|
140 } else { |
|
141 return LookupHelper.PUBLIC_LOOKUP; |
|
142 } |
|
143 } |
140 } |
144 |
141 |
145 /** |
142 /** |
146 * Returns a {@link Lookup lookup object} with full capabilities to emulate all |
143 * Returns a {@link Lookup lookup object} with full capabilities to emulate all |
147 * supported bytecode behaviors, including <a href="MethodHandles.Lookup.html#privacc"> |
144 * supported bytecode behaviors, including <a href="MethodHandles.Lookup.html#privacc"> |
170 * @throws IllegalArgumentException if {@code targetClass} is a primitve type or array class |
167 * @throws IllegalArgumentException if {@code targetClass} is a primitve type or array class |
171 * @throws NullPointerException if {@code targetClass} or {@code caller} is {@code null} |
168 * @throws NullPointerException if {@code targetClass} or {@code caller} is {@code null} |
172 * @throws IllegalAccessException if the access check specified above fails |
169 * @throws IllegalAccessException if the access check specified above fails |
173 * @throws SecurityException if denied by the security manager |
170 * @throws SecurityException if denied by the security manager |
174 * @since 9 |
171 * @since 9 |
|
172 * @spec JPMS |
175 * @see Lookup#dropLookupMode |
173 * @see Lookup#dropLookupMode |
176 */ |
174 */ |
177 public static Lookup privateLookupIn(Class<?> targetClass, Lookup lookup) throws IllegalAccessException { |
175 public static Lookup privateLookupIn(Class<?> targetClass, Lookup lookup) throws IllegalAccessException { |
178 SecurityManager sm = System.getSecurityManager(); |
176 SecurityManager sm = System.getSecurityManager(); |
179 if (sm != null) sm.checkPermission(ACCESS_PERMISSION); |
177 if (sm != null) sm.checkPermission(ACCESS_PERMISSION); |
181 throw new IllegalArgumentException(targetClass + " is a primitive class"); |
179 throw new IllegalArgumentException(targetClass + " is a primitive class"); |
182 if (targetClass.isArray()) |
180 if (targetClass.isArray()) |
183 throw new IllegalArgumentException(targetClass + " is an array class"); |
181 throw new IllegalArgumentException(targetClass + " is an array class"); |
184 Module targetModule = targetClass.getModule(); |
182 Module targetModule = targetClass.getModule(); |
185 Module callerModule = lookup.lookupClass().getModule(); |
183 Module callerModule = lookup.lookupClass().getModule(); |
186 if (callerModule != targetModule && targetModule.isNamed()) { |
184 if (!callerModule.canRead(targetModule)) |
187 if (!callerModule.canRead(targetModule)) |
185 throw new IllegalAccessException(callerModule + " does not read " + targetModule); |
188 throw new IllegalAccessException(callerModule + " does not read " + targetModule); |
186 if (targetModule.isNamed()) { |
189 String pn = targetClass.getPackageName(); |
187 String pn = targetClass.getPackageName(); |
190 assert pn != null && pn.length() > 0 : "unnamed package cannot be in named module"; |
188 assert pn.length() > 0 : "unnamed package cannot be in named module"; |
191 if (!targetModule.isOpen(pn, callerModule)) |
189 if (!targetModule.isOpen(pn, callerModule)) |
192 throw new IllegalAccessException(targetModule + " does not open " + pn + " to " + callerModule); |
190 throw new IllegalAccessException(targetModule + " does not open " + pn + " to " + callerModule); |
193 } |
191 } |
194 if ((lookup.lookupModes() & Lookup.MODULE) == 0) |
192 if ((lookup.lookupModes() & Lookup.MODULE) == 0) |
195 throw new IllegalAccessException("lookup does not have MODULE lookup mode"); |
193 throw new IllegalAccessException("lookup does not have MODULE lookup mode"); |
599 * <p style="font-size:smaller;"> |
597 * <p style="font-size:smaller;"> |
600 * The function {@code MethodHandles.lookup} is caller sensitive |
598 * The function {@code MethodHandles.lookup} is caller sensitive |
601 * so that there can be a secure foundation for lookups. |
599 * so that there can be a secure foundation for lookups. |
602 * Nearly all other methods in the JSR 292 API rely on lookup |
600 * Nearly all other methods in the JSR 292 API rely on lookup |
603 * objects to check access requests. |
601 * objects to check access requests. |
|
602 * |
|
603 * @revised 9 |
604 */ |
604 */ |
605 public static final |
605 public static final |
606 class Lookup { |
606 class Lookup { |
607 /** The class on behalf of whom the lookup is being performed. */ |
607 /** The class on behalf of whom the lookup is being performed. */ |
608 private final Class<?> lookupClass; |
608 private final Class<?> lookupClass; |
645 * In conjunction with the {@code PUBLIC} modifier bit, a {@code Lookup} |
645 * In conjunction with the {@code PUBLIC} modifier bit, a {@code Lookup} |
646 * with this lookup mode can access all public types in the module of the |
646 * with this lookup mode can access all public types in the module of the |
647 * lookup class and public types in packages exported by other modules |
647 * lookup class and public types in packages exported by other modules |
648 * to the module of the lookup class. |
648 * to the module of the lookup class. |
649 * @since 9 |
649 * @since 9 |
|
650 * @spec JPMS |
650 */ |
651 */ |
651 public static final int MODULE = PACKAGE << 1; |
652 public static final int MODULE = PACKAGE << 1; |
652 |
653 |
653 private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE | MODULE); |
654 /** A single-bit mask representing {@code unconditional} access |
|
655 * which may contribute to the result of {@link #lookupModes lookupModes}. |
|
656 * The value is {@code 0x20}, which does not correspond meaningfully to |
|
657 * any particular {@linkplain java.lang.reflect.Modifier modifier bit}. |
|
658 * A {@code Lookup} with this lookup mode assumes {@linkplain |
|
659 * java.lang.reflect.Module#canRead(java.lang.reflect.Module) readability}. |
|
660 * In conjunction with the {@code PUBLIC} modifier bit, a {@code Lookup} |
|
661 * with this lookup mode can access all public members of public types |
|
662 * of all modules where the type is in a package that is {@link |
|
663 * java.lang.reflect.Module#isExported(String) exported unconditionally}. |
|
664 * @since 9 |
|
665 * @spec JPMS |
|
666 * @see #publicLookup() |
|
667 */ |
|
668 public static final int UNCONDITIONAL = PACKAGE << 2; |
|
669 |
|
670 private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE | MODULE | UNCONDITIONAL); |
|
671 private static final int FULL_POWER_MODES = (ALL_MODES & ~UNCONDITIONAL); |
654 private static final int TRUSTED = -1; |
672 private static final int TRUSTED = -1; |
655 |
673 |
656 private static int fixmods(int mods) { |
674 private static int fixmods(int mods) { |
657 mods &= (ALL_MODES - PACKAGE - MODULE); |
675 mods &= (ALL_MODES - PACKAGE - MODULE - UNCONDITIONAL); |
658 return (mods != 0) ? mods : (PACKAGE | MODULE); |
676 return (mods != 0) ? mods : (PACKAGE | MODULE | UNCONDITIONAL); |
659 } |
677 } |
660 |
678 |
661 /** Tells which class is performing the lookup. It is this class against |
679 /** Tells which class is performing the lookup. It is this class against |
662 * which checks are performed for visibility and access permissions. |
680 * which checks are performed for visibility and access permissions. |
663 * <p> |
681 * <p> |
680 * The result is a bit-mask of the bits |
698 * The result is a bit-mask of the bits |
681 * {@linkplain #PUBLIC PUBLIC (0x01)}, |
699 * {@linkplain #PUBLIC PUBLIC (0x01)}, |
682 * {@linkplain #PRIVATE PRIVATE (0x02)}, |
700 * {@linkplain #PRIVATE PRIVATE (0x02)}, |
683 * {@linkplain #PROTECTED PROTECTED (0x04)}, |
701 * {@linkplain #PROTECTED PROTECTED (0x04)}, |
684 * {@linkplain #PACKAGE PACKAGE (0x08)}, |
702 * {@linkplain #PACKAGE PACKAGE (0x08)}, |
685 * and {@linkplain #MODULE MODULE (0x10)}. |
703 * {@linkplain #MODULE MODULE (0x10)}, |
|
704 * and {@linkplain #UNCONDITIONAL UNCONDITIONAL (0x20)}. |
686 * <p> |
705 * <p> |
687 * A freshly-created lookup object |
706 * A freshly-created lookup object |
688 * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} |
707 * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has |
689 * has all possible bits set, since the caller class can access all its own members, |
708 * all possible bits set, except {@code UNCONDITIONAL}. The lookup can be used to |
690 * all public types in the caller's module, and all public types in packages exported |
709 * access all members of the caller's class, all public types in the caller's module, |
691 * by other modules to the caller's module. |
710 * and all public types in packages exported by other modules to the caller's module. |
692 * A lookup object on a new lookup class |
711 * A lookup object on a new lookup class |
693 * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object} |
712 * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object} |
694 * may have some mode bits set to zero. |
713 * may have some mode bits set to zero. |
695 * Mode bits can also be |
714 * Mode bits can also be |
696 * {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}. |
715 * {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}. |
699 * so that it can access only names which can be reached by the original |
718 * so that it can access only names which can be reached by the original |
700 * lookup object, and also by the new lookup class. |
719 * lookup object, and also by the new lookup class. |
701 * @return the lookup modes, which limit the kinds of access performed by this lookup object |
720 * @return the lookup modes, which limit the kinds of access performed by this lookup object |
702 * @see #in |
721 * @see #in |
703 * @see #dropLookupMode |
722 * @see #dropLookupMode |
|
723 * |
|
724 * @revised 9 |
|
725 * @spec JPMS |
704 */ |
726 */ |
705 public int lookupModes() { |
727 public int lookupModes() { |
706 return allowedModes & ALL_MODES; |
728 return allowedModes & ALL_MODES; |
707 } |
729 } |
708 |
730 |
710 * for method handle creation. |
732 * for method handle creation. |
711 * Must be called by from a method in this package, |
733 * Must be called by from a method in this package, |
712 * which in turn is called by a method not in this package. |
734 * which in turn is called by a method not in this package. |
713 */ |
735 */ |
714 Lookup(Class<?> lookupClass) { |
736 Lookup(Class<?> lookupClass) { |
715 this(lookupClass, ALL_MODES); |
737 this(lookupClass, FULL_POWER_MODES); |
716 // make sure we haven't accidentally picked up a privileged class: |
738 // make sure we haven't accidentally picked up a privileged class: |
717 checkUnprivilegedlookupClass(lookupClass, ALL_MODES); |
739 checkUnprivilegedlookupClass(lookupClass, FULL_POWER_MODES); |
718 } |
740 } |
719 |
741 |
720 private Lookup(Class<?> lookupClass, int allowedModes) { |
742 private Lookup(Class<?> lookupClass, int allowedModes) { |
721 this.lookupClass = lookupClass; |
743 this.lookupClass = lookupClass; |
722 this.allowedModes = allowedModes; |
744 this.allowedModes = allowedModes; |
728 * class as its own {@link #lookupClass lookupClass}. |
750 * class as its own {@link #lookupClass lookupClass}. |
729 * <p> |
751 * <p> |
730 * However, the resulting {@code Lookup} object is guaranteed |
752 * However, the resulting {@code Lookup} object is guaranteed |
731 * to have no more access capabilities than the original. |
753 * to have no more access capabilities than the original. |
732 * In particular, access capabilities can be lost as follows:<ul> |
754 * In particular, access capabilities can be lost as follows:<ul> |
733 * <li>If the lookup class for this {@code Lookup} is not in a named module, |
755 * <li>If the old lookup class is in a {@link Module#isNamed() named} module, and |
734 * and the new lookup class is in a named module {@code M}, then no members in |
756 * the new lookup class is in a different module {@code M}, then no members, not |
735 * {@code M}'s non-exported packages will be accessible. |
757 * even public members in {@code M}'s exported packages, will be accessible. |
736 * <li>If the lookup for this {@code Lookup} is in a named module, and the |
758 * The exception to this is when this lookup is {@link #publicLookup() |
737 * new lookup class is in a different module {@code M}, then no members, not even |
759 * publicLookup}, in which case {@code PUBLIC} access is not lost. |
738 * public members in {@code M}'s exported packages, will be accessible. |
760 * <li>If the old lookup class is in an unnamed module, and the new lookup class |
739 * <li>If the new lookup class differs from the old one, |
761 * is a different module then {@link #MODULE MODULE} access is lost. |
740 * protected members will not be accessible by virtue of inheritance. |
762 * <li>If the new lookup class differs from the old one then {@code UNCONDITIONAL} is lost. |
741 * (Protected members may continue to be accessible because of package sharing.) |
|
742 * <li>If the new lookup class is in a different package |
763 * <li>If the new lookup class is in a different package |
743 * than the old one, protected and default (package) members will not be accessible. |
764 * than the old one, protected and default (package) members will not be accessible. |
744 * <li>If the new lookup class is not within the same package member |
765 * <li>If the new lookup class is not within the same package member |
745 * as the old one, private members will not be accessible. |
766 * as the old one, private members will not be accessible, and protected members |
|
767 * will not be accessible by virtue of inheritance. |
|
768 * (Protected members may continue to be accessible because of package sharing.) |
746 * <li>If the new lookup class is not accessible to the old lookup class, |
769 * <li>If the new lookup class is not accessible to the old lookup class, |
747 * then no members, not even public members, will be accessible. |
770 * then no members, not even public members, will be accessible. |
748 * (In all other cases, public members will continue to be accessible.) |
771 * (In all other cases, public members will continue to be accessible.) |
749 * </ul> |
772 * </ul> |
750 * <p> |
773 * <p> |
755 * |
778 * |
756 * @param requestedLookupClass the desired lookup class for the new lookup object |
779 * @param requestedLookupClass the desired lookup class for the new lookup object |
757 * @return a lookup object which reports the desired lookup class, or the same object |
780 * @return a lookup object which reports the desired lookup class, or the same object |
758 * if there is no change |
781 * if there is no change |
759 * @throws NullPointerException if the argument is null |
782 * @throws NullPointerException if the argument is null |
|
783 * |
|
784 * @revised 9 |
|
785 * @spec JPMS |
760 */ |
786 */ |
761 public Lookup in(Class<?> requestedLookupClass) { |
787 public Lookup in(Class<?> requestedLookupClass) { |
762 Objects.requireNonNull(requestedLookupClass); |
788 Objects.requireNonNull(requestedLookupClass); |
763 if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all |
789 if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all |
764 return new Lookup(requestedLookupClass, ALL_MODES); |
790 return new Lookup(requestedLookupClass, FULL_POWER_MODES); |
765 if (requestedLookupClass == this.lookupClass) |
791 if (requestedLookupClass == this.lookupClass) |
766 return this; // keep same capabilities |
792 return this; // keep same capabilities |
767 |
793 int newModes = (allowedModes & FULL_POWER_MODES); |
768 int newModes = (allowedModes & (ALL_MODES & ~PROTECTED)); |
|
769 if (!VerifyAccess.isSameModule(this.lookupClass, requestedLookupClass)) { |
794 if (!VerifyAccess.isSameModule(this.lookupClass, requestedLookupClass)) { |
770 // Allowed to teleport from an unnamed to a named module but resulting |
795 // Need to drop all access when teleporting from a named module to another |
771 // Lookup has no access to module private members |
796 // module. The exception is publicLookup where PUBLIC is not lost. |
772 if (this.lookupClass.getModule().isNamed()) { |
797 if (this.lookupClass.getModule().isNamed() |
|
798 && (this.allowedModes & UNCONDITIONAL) == 0) |
773 newModes = 0; |
799 newModes = 0; |
774 } else { |
800 else |
775 newModes &= ~MODULE; |
801 newModes &= ~(MODULE|PACKAGE|PRIVATE|PROTECTED); |
776 } |
|
777 } |
802 } |
778 if ((newModes & PACKAGE) != 0 |
803 if ((newModes & PACKAGE) != 0 |
779 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) { |
804 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) { |
780 newModes &= ~(PACKAGE|PRIVATE); |
805 newModes &= ~(PACKAGE|PRIVATE|PROTECTED); |
781 } |
806 } |
782 // Allow nestmate lookups to be created without special privilege: |
807 // Allow nestmate lookups to be created without special privilege: |
783 if ((newModes & PRIVATE) != 0 |
808 if ((newModes & PRIVATE) != 0 |
784 && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) { |
809 && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) { |
785 newModes &= ~PRIVATE; |
810 newModes &= ~(PRIVATE|PROTECTED); |
786 } |
811 } |
787 if ((newModes & PUBLIC) != 0 |
812 if ((newModes & PUBLIC) != 0 |
788 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) { |
813 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) { |
789 // The requested class it not accessible from the lookup class. |
814 // The requested class it not accessible from the lookup class. |
790 // No permissions. |
815 // No permissions. |
799 /** |
824 /** |
800 * Creates a lookup on the same lookup class which this lookup object |
825 * Creates a lookup on the same lookup class which this lookup object |
801 * finds members, but with a lookup mode that has lost the given lookup mode. |
826 * finds members, but with a lookup mode that has lost the given lookup mode. |
802 * The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE |
827 * The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE |
803 * MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED} or {@link #PRIVATE PRIVATE}. |
828 * MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED} or {@link #PRIVATE PRIVATE}. |
804 * {@link #PROTECTED PROTECTED} is always dropped and so the resulting lookup |
829 * {@link #PROTECTED PROTECTED} and {@link #UNCONDITIONAL UNCONDITIONAL} are always |
805 * mode will never have this access capability. When dropping {@code PACKAGE} |
830 * dropped and so the resulting lookup mode will never have these access capabilities. |
806 * then the resulting lookup will not have {@code PACKAGE} or {@code PRIVATE} |
831 * When dropping {@code PACKAGE} then the resulting lookup will not have {@code PACKAGE} |
807 * access. When dropping {@code MODULE} then the resulting lookup will not |
832 * or {@code PRIVATE} access. When dropping {@code MODULE} then the resulting lookup will |
808 * have {@code MODULE}, {@code PACKAGE}, or {@code PRIVATE} access. If {@code |
833 * not have {@code MODULE}, {@code PACKAGE}, or {@code PRIVATE} access. If {@code PUBLIC} |
809 * PUBLIC} is dropped then the resulting lookup has no access. |
834 * is dropped then the resulting lookup has no access. |
810 * @param modeToDrop the lookup mode to drop |
835 * @param modeToDrop the lookup mode to drop |
811 * @return a lookup object which lacks the indicated mode, or the same object if there is no change |
836 * @return a lookup object which lacks the indicated mode, or the same object if there is no change |
812 * @throws IllegalArgumentException if {@code modeToDrop} is not one of {@code PUBLIC}, |
837 * @throws IllegalArgumentException if {@code modeToDrop} is not one of {@code PUBLIC}, |
813 * {@code MODULE}, {@code PACKAGE}, {@code PROTECTED} or {@code PRIVATE} |
838 * {@code MODULE}, {@code PACKAGE}, {@code PROTECTED}, {@code PRIVATE} or {@code UNCONDITIONAL} |
|
839 * @see MethodHandles#privateLookupIn |
814 * @since 9 |
840 * @since 9 |
815 * @see MethodHandles#privateLookupIn |
|
816 */ |
841 */ |
817 public Lookup dropLookupMode(int modeToDrop) { |
842 public Lookup dropLookupMode(int modeToDrop) { |
818 int oldModes = lookupModes(); |
843 int oldModes = lookupModes(); |
819 int newModes = oldModes & ~(modeToDrop | PROTECTED); |
844 int newModes = oldModes & ~(modeToDrop | PROTECTED | UNCONDITIONAL); |
820 switch (modeToDrop) { |
845 switch (modeToDrop) { |
821 case PUBLIC: newModes &= ~(ALL_MODES); break; |
846 case PUBLIC: newModes &= ~(ALL_MODES); break; |
822 case MODULE: newModes &= ~(PACKAGE | PRIVATE); break; |
847 case MODULE: newModes &= ~(PACKAGE | PRIVATE); break; |
823 case PACKAGE: newModes &= ~(PRIVATE); break; |
848 case PACKAGE: newModes &= ~(PRIVATE); break; |
824 case PROTECTED: |
849 case PROTECTED: |
825 case PRIVATE: break; |
850 case PRIVATE: |
|
851 case UNCONDITIONAL: break; |
826 default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop"); |
852 default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop"); |
827 } |
853 } |
828 if (newModes == oldModes) return this; // return self if no change |
854 if (newModes == oldModes) return this; // return self if no change |
829 return new Lookup(lookupClass(), newModes); |
855 return new Lookup(lookupClass(), newModes); |
830 } |
856 } |
832 // Make sure outer class is initialized first. |
858 // Make sure outer class is initialized first. |
833 static { IMPL_NAMES.getClass(); } |
859 static { IMPL_NAMES.getClass(); } |
834 |
860 |
835 /** Package-private version of lookup which is trusted. */ |
861 /** Package-private version of lookup which is trusted. */ |
836 static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED); |
862 static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED); |
|
863 |
|
864 /** Version of lookup which is trusted minimally. |
|
865 * It can only be used to create method handles to publicly accessible |
|
866 * members in packages that are exported unconditionally. |
|
867 */ |
|
868 static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, (PUBLIC|UNCONDITIONAL)); |
837 |
869 |
838 private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) { |
870 private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) { |
839 String name = lookupClass.getName(); |
871 String name = lookupClass.getName(); |
840 if (name.startsWith("java.lang.invoke.")) |
872 if (name.startsWith("java.lang.invoke.")) |
841 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); |
873 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); |
843 // For caller-sensitive MethodHandles.lookup() disallow lookup from |
875 // For caller-sensitive MethodHandles.lookup() disallow lookup from |
844 // restricted packages. This a fragile and blunt approach. |
876 // restricted packages. This a fragile and blunt approach. |
845 // TODO replace with a more formal and less fragile mechanism |
877 // TODO replace with a more formal and less fragile mechanism |
846 // that does not bluntly restrict classes under packages within |
878 // that does not bluntly restrict classes under packages within |
847 // java.base from looking up MethodHandles or VarHandles. |
879 // java.base from looking up MethodHandles or VarHandles. |
848 if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) { |
880 if (allowedModes == FULL_POWER_MODES && lookupClass.getClassLoader() == null) { |
849 if ((name.startsWith("java.") && |
881 if ((name.startsWith("java.") && |
850 !name.equals("java.lang.Thread") && |
882 !name.equals("java.lang.Thread") && |
851 !name.startsWith("java.util.concurrent.")) || |
883 !name.startsWith("java.util.concurrent.")) || |
852 (name.startsWith("sun.") && |
884 (name.startsWith("sun.") && |
853 !name.startsWith("sun.invoke."))) { |
885 !name.startsWith("sun.invoke."))) { |
864 * of a slash and a keyword. The keyword represents the strongest |
896 * of a slash and a keyword. The keyword represents the strongest |
865 * allowed access, and is chosen as follows: |
897 * allowed access, and is chosen as follows: |
866 * <ul> |
898 * <ul> |
867 * <li>If no access is allowed, the suffix is "/noaccess". |
899 * <li>If no access is allowed, the suffix is "/noaccess". |
868 * <li>If only public access to types in exported packages is allowed, the suffix is "/public". |
900 * <li>If only public access to types in exported packages is allowed, the suffix is "/public". |
|
901 * <li>If only public access and unconditional access are allowed, the suffix is "/publicLookup". |
869 * <li>If only public and module access are allowed, the suffix is "/module". |
902 * <li>If only public and module access are allowed, the suffix is "/module". |
870 * <li>If only public, module and package access are allowed, the suffix is "/package". |
903 * <li>If only public, module and package access are allowed, the suffix is "/package". |
871 * <li>If only public, module, package, and private access are allowed, the suffix is "/private". |
904 * <li>If only public, module, package, and private access are allowed, the suffix is "/private". |
872 * </ul> |
905 * </ul> |
873 * If none of the above cases apply, it is the case that full |
906 * If none of the above cases apply, it is the case that full |
882 * stronger than private access. Viewed independently from |
915 * stronger than private access. Viewed independently from |
883 * package access, protected access is the first to be lost, |
916 * package access, protected access is the first to be lost, |
884 * because it requires a direct subclass relationship between |
917 * because it requires a direct subclass relationship between |
885 * caller and callee.) |
918 * caller and callee.) |
886 * @see #in |
919 * @see #in |
|
920 * |
|
921 * @revised 9 |
|
922 * @spec JPMS |
887 */ |
923 */ |
888 @Override |
924 @Override |
889 public String toString() { |
925 public String toString() { |
890 String cname = lookupClass.getName(); |
926 String cname = lookupClass.getName(); |
891 switch (allowedModes) { |
927 switch (allowedModes) { |
892 case 0: // no privileges |
928 case 0: // no privileges |
893 return cname + "/noaccess"; |
929 return cname + "/noaccess"; |
894 case PUBLIC: |
930 case PUBLIC: |
895 return cname + "/public"; |
931 return cname + "/public"; |
|
932 case PUBLIC|UNCONDITIONAL: |
|
933 return cname + "/publicLookup"; |
896 case PUBLIC|MODULE: |
934 case PUBLIC|MODULE: |
897 return cname + "/module"; |
935 return cname + "/module"; |
898 case PUBLIC|MODULE|PACKAGE: |
936 case PUBLIC|MODULE|PACKAGE: |
899 return cname + "/package"; |
937 return cname + "/package"; |
900 case ALL_MODES & ~PROTECTED: |
938 case FULL_POWER_MODES & ~PROTECTED: |
901 return cname + "/private"; |
939 return cname + "/private"; |
902 case ALL_MODES: |
940 case FULL_POWER_MODES: |
903 return cname; |
941 return cname; |
904 case TRUSTED: |
942 case TRUSTED: |
905 return "/trusted"; // internal only; not exported |
943 return "/trusted"; // internal only; not exported |
906 default: // Should not happen, but it's a bitfield... |
944 default: // Should not happen, but it's a bitfield... |
907 cname = cname + "/" + Integer.toHexString(allowedModes); |
945 cname = cname + "/" + Integer.toHexString(allowedModes); |
1578 MemberName method = new MemberName(m); |
1616 MemberName method = new MemberName(m); |
1579 byte refKind = method.getReferenceKind(); |
1617 byte refKind = method.getReferenceKind(); |
1580 if (refKind == REF_invokeSpecial) |
1618 if (refKind == REF_invokeSpecial) |
1581 refKind = REF_invokeVirtual; |
1619 refKind = REF_invokeVirtual; |
1582 assert(method.isMethod()); |
1620 assert(method.isMethod()); |
|
1621 @SuppressWarnings("deprecation") |
1583 Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; |
1622 Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; |
1584 return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method)); |
1623 return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method)); |
1585 } |
1624 } |
1586 private MethodHandle unreflectForMH(Method m) { |
1625 private MethodHandle unreflectForMH(Method m) { |
1587 // these names require special lookups because they throw UnsupportedOperationException |
1626 // these names require special lookups because they throw UnsupportedOperationException |
1660 * @throws NullPointerException if the argument is null |
1699 * @throws NullPointerException if the argument is null |
1661 */ |
1700 */ |
1662 public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException { |
1701 public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException { |
1663 MemberName ctor = new MemberName(c); |
1702 MemberName ctor = new MemberName(c); |
1664 assert(ctor.isConstructor()); |
1703 assert(ctor.isConstructor()); |
|
1704 @SuppressWarnings("deprecation") |
1665 Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this; |
1705 Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this; |
1666 return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor); |
1706 return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor); |
1667 } |
1707 } |
1668 |
1708 |
1669 /** |
1709 /** |
1690 private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException { |
1730 private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException { |
1691 MemberName field = new MemberName(f, isSetter); |
1731 MemberName field = new MemberName(f, isSetter); |
1692 assert(isSetter |
1732 assert(isSetter |
1693 ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind()) |
1733 ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind()) |
1694 : MethodHandleNatives.refKindIsGetter(field.getReferenceKind())); |
1734 : MethodHandleNatives.refKindIsGetter(field.getReferenceKind())); |
|
1735 @SuppressWarnings("deprecation") |
1695 Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this; |
1736 Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this; |
1696 return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field); |
1737 return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field); |
1697 } |
1738 } |
1698 |
1739 |
1699 /** |
1740 /** |
2031 // check the class first: |
2072 // check the class first: |
2032 boolean classOK = (Modifier.isPublic(defc.getModifiers()) && |
2073 boolean classOK = (Modifier.isPublic(defc.getModifiers()) && |
2033 (defc == refc || |
2074 (defc == refc || |
2034 Modifier.isPublic(refc.getModifiers()))); |
2075 Modifier.isPublic(refc.getModifiers()))); |
2035 if (!classOK && (allowedModes & PACKAGE) != 0) { |
2076 if (!classOK && (allowedModes & PACKAGE) != 0) { |
2036 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), ALL_MODES) && |
2077 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), FULL_POWER_MODES) && |
2037 (defc == refc || |
2078 (defc == refc || |
2038 VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES))); |
2079 VerifyAccess.isClassAccessible(refc, lookupClass(), FULL_POWER_MODES))); |
2039 } |
2080 } |
2040 if (!classOK) |
2081 if (!classOK) |
2041 return "class is not public"; |
2082 return "class is not public"; |
2042 if (Modifier.isPublic(mods)) |
2083 if (Modifier.isPublic(mods)) |
2043 return "access to public member failed"; // (how?, module not readable?) |
2084 return "access to public member failed"; // (how?, module not readable?) |
2343 // oops |
2384 // oops |
2344 throw newIllegalArgumentException("bad MethodHandle constant #"+member); |
2385 throw newIllegalArgumentException("bad MethodHandle constant #"+member); |
2345 } |
2386 } |
2346 |
2387 |
2347 static ConcurrentHashMap<MemberName, DirectMethodHandle> LOOKASIDE_TABLE = new ConcurrentHashMap<>(); |
2388 static ConcurrentHashMap<MemberName, DirectMethodHandle> LOOKASIDE_TABLE = new ConcurrentHashMap<>(); |
2348 } |
|
2349 |
|
2350 /** |
|
2351 * Helper class used to lazily create PUBLIC_LOOKUP with a lookup class |
|
2352 * in an <em>unnamed module</em>. |
|
2353 * |
|
2354 * @see Lookup#publicLookup |
|
2355 */ |
|
2356 private static class LookupHelper { |
|
2357 private static final String UNNAMED = "Unnamed"; |
|
2358 private static final String OBJECT = "java/lang/Object"; |
|
2359 |
|
2360 private static Class<?> createClass() { |
|
2361 try { |
|
2362 ClassWriter cw = new ClassWriter(0); |
|
2363 cw.visit(Opcodes.V1_8, |
|
2364 Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, |
|
2365 UNNAMED, |
|
2366 null, |
|
2367 OBJECT, |
|
2368 null); |
|
2369 cw.visitSource(UNNAMED, null); |
|
2370 cw.visitEnd(); |
|
2371 byte[] bytes = cw.toByteArray(); |
|
2372 ClassLoader loader = new ClassLoader(null) { |
|
2373 @Override |
|
2374 protected Class<?> findClass(String cn) throws ClassNotFoundException { |
|
2375 if (cn.equals(UNNAMED)) |
|
2376 return super.defineClass(UNNAMED, bytes, 0, bytes.length); |
|
2377 throw new ClassNotFoundException(cn); |
|
2378 } |
|
2379 }; |
|
2380 return loader.loadClass(UNNAMED); |
|
2381 } catch (Exception e) { |
|
2382 throw new InternalError(e); |
|
2383 } |
|
2384 } |
|
2385 |
|
2386 private static final Class<?> PUBLIC_LOOKUP_CLASS = createClass(); |
|
2387 |
|
2388 /** |
|
2389 * Lookup that is trusted minimally. It can only be used to create |
|
2390 * method handles to publicly accessible members in exported packages. |
|
2391 * |
|
2392 * @see MethodHandles#publicLookup |
|
2393 */ |
|
2394 static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_LOOKUP_CLASS, Lookup.PUBLIC); |
|
2395 } |
2389 } |
2396 |
2390 |
2397 /** |
2391 /** |
2398 * Produces a method handle constructing arrays of a desired type. |
2392 * Produces a method handle constructing arrays of a desired type. |
2399 * The return type of the method handle will be the array type. |
2393 * The return type of the method handle will be the array type. |