< prev index next >

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

Print this page

        

*** 23,34 **** * questions. */ package java.lang.invoke; - import jdk.internal.org.objectweb.asm.ClassWriter; - import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.vm.annotation.ForceInline; import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyAccess; --- 23,32 ----
*** 109,125 **** return new Lookup(Reflection.getCallerClass()); } /** * Returns a {@link Lookup lookup object} which is trusted minimally. ! * It can only be used to create method handles to public members in * public classes in packages that are exported unconditionally. * <p> ! * For now, the {@linkplain Lookup#lookupClass lookup class} of this lookup ! * object is in an unnamed module. ! * Consequently, the lookup context of this lookup object will be the bootstrap ! * class loader, which means it cannot find user classes. * * <p style="font-size:smaller;"> * <em>Discussion:</em> * The lookup class can be changed to any other class {@code C} using an expression of the form * {@link Lookup#in publicLookup().in(C.class)}. --- 107,127 ---- return new Lookup(Reflection.getCallerClass()); } /** * Returns a {@link Lookup lookup object} which is trusted minimally. ! * The lookup has the {@code PUBLIC} and {@code UNCONDITIONAL} modes. ! * It can only be used to create method handles to public members of * public classes in packages that are exported unconditionally. * <p> ! * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class} ! * of this lookup object will be {@link java.lang.Object}. ! * ! * @apiNote The use of Object is conventional, and because the lookup modes are ! * limited, there is no special access provided to the internals of Object, its package ! * or its module. Consequently, the lookup context of this lookup object will be the ! * bootstrap class loader, which means it cannot find user classes. * * <p style="font-size:smaller;"> * <em>Discussion:</em> * The lookup class can be changed to any other class {@code C} using an expression of the form * {@link Lookup#in publicLookup().in(C.class)}.
*** 127,147 **** * A public lookup object is always subject to * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>. * Also, it cannot access * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>. * @return a lookup object which is trusted minimally */ public static Lookup publicLookup() { ! // During VM startup then only classes in the java.base module can be ! // loaded and linked. This is because java.base exports aren't setup until ! // the module system is initialized, hence types in the unnamed module ! // (or any named module) can't link to java/lang/Object. ! if (!jdk.internal.misc.VM.isModuleSystemInited()) { ! return new Lookup(Object.class, Lookup.PUBLIC); ! } else { ! return LookupHelper.PUBLIC_LOOKUP; ! } } /** * Returns a {@link Lookup lookup object} with full capabilities to emulate all * supported bytecode behaviors, including <a href="MethodHandles.Lookup.html#privacc"> --- 129,144 ---- * A public lookup object is always subject to * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>. * Also, it cannot access * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>. * @return a lookup object which is trusted minimally + * + * @revised 9 + * @spec JPMS */ public static Lookup publicLookup() { ! return Lookup.PUBLIC_LOOKUP; } /** * Returns a {@link Lookup lookup object} with full capabilities to emulate all * supported bytecode behaviors, including <a href="MethodHandles.Lookup.html#privacc">
*** 170,179 **** --- 167,177 ---- * @throws IllegalArgumentException if {@code targetClass} is a primitve type or array class * @throws NullPointerException if {@code targetClass} or {@code caller} is {@code null} * @throws IllegalAccessException if the access check specified above fails * @throws SecurityException if denied by the security manager * @since 9 + * @spec JPMS * @see Lookup#dropLookupMode */ public static Lookup privateLookupIn(Class<?> targetClass, Lookup lookup) throws IllegalAccessException { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
*** 181,195 **** throw new IllegalArgumentException(targetClass + " is a primitive class"); if (targetClass.isArray()) throw new IllegalArgumentException(targetClass + " is an array class"); Module targetModule = targetClass.getModule(); Module callerModule = lookup.lookupClass().getModule(); - if (callerModule != targetModule && targetModule.isNamed()) { if (!callerModule.canRead(targetModule)) throw new IllegalAccessException(callerModule + " does not read " + targetModule); String pn = targetClass.getPackageName(); ! assert pn != null && pn.length() > 0 : "unnamed package cannot be in named module"; if (!targetModule.isOpen(pn, callerModule)) throw new IllegalAccessException(targetModule + " does not open " + pn + " to " + callerModule); } if ((lookup.lookupModes() & Lookup.MODULE) == 0) throw new IllegalAccessException("lookup does not have MODULE lookup mode"); --- 179,193 ---- throw new IllegalArgumentException(targetClass + " is a primitive class"); if (targetClass.isArray()) throw new IllegalArgumentException(targetClass + " is an array class"); Module targetModule = targetClass.getModule(); Module callerModule = lookup.lookupClass().getModule(); if (!callerModule.canRead(targetModule)) throw new IllegalAccessException(callerModule + " does not read " + targetModule); + if (targetModule.isNamed()) { String pn = targetClass.getPackageName(); ! assert pn.length() > 0 : "unnamed package cannot be in named module"; if (!targetModule.isOpen(pn, callerModule)) throw new IllegalAccessException(targetModule + " does not open " + pn + " to " + callerModule); } if ((lookup.lookupModes() & Lookup.MODULE) == 0) throw new IllegalAccessException("lookup does not have MODULE lookup mode");
*** 599,608 **** --- 597,608 ---- * <p style="font-size:smaller;"> * The function {@code MethodHandles.lookup} is caller sensitive * so that there can be a secure foundation for lookups. * Nearly all other methods in the JSR 292 API rely on lookup * objects to check access requests. + * + * @revised 9 */ public static final class Lookup { /** The class on behalf of whom the lookup is being performed. */ private final Class<?> lookupClass;
*** 645,663 **** * In conjunction with the {@code PUBLIC} modifier bit, a {@code Lookup} * with this lookup mode can access all public types in the module of the * lookup class and public types in packages exported by other modules * to the module of the lookup class. * @since 9 */ public static final int MODULE = PACKAGE << 1; ! private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE | MODULE); private static final int TRUSTED = -1; private static int fixmods(int mods) { ! mods &= (ALL_MODES - PACKAGE - MODULE); ! return (mods != 0) ? mods : (PACKAGE | MODULE); } /** Tells which class is performing the lookup. It is this class against * which checks are performed for visibility and access permissions. * <p> --- 645,680 ---- * In conjunction with the {@code PUBLIC} modifier bit, a {@code Lookup} * with this lookup mode can access all public types in the module of the * lookup class and public types in packages exported by other modules * to the module of the lookup class. * @since 9 + * @spec JPMS */ public static final int MODULE = PACKAGE << 1; ! /** A single-bit mask representing {@code unconditional} access ! * which may contribute to the result of {@link #lookupModes lookupModes}. ! * The value is {@code 0x20}, which does not correspond meaningfully to ! * any particular {@linkplain java.lang.reflect.Modifier modifier bit}. ! * A {@code Lookup} with this lookup mode assumes {@linkplain ! * java.lang.reflect.Module#canRead(java.lang.reflect.Module) readability}. ! * In conjunction with the {@code PUBLIC} modifier bit, a {@code Lookup} ! * with this lookup mode can access all public members of public types ! * of all modules where the type is in a package that is {@link ! * java.lang.reflect.Module#isExported(String) exported unconditionally}. ! * @see #publicLookup() ! * @since 9 ! */ ! public static final int UNCONDITIONAL = PACKAGE << 2; ! ! private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE | MODULE | UNCONDITIONAL); ! private static final int FULL_POWER_MODES = (ALL_MODES & ~UNCONDITIONAL); private static final int TRUSTED = -1; private static int fixmods(int mods) { ! mods &= (ALL_MODES - PACKAGE - MODULE - UNCONDITIONAL); ! return (mods != 0) ? mods : (PACKAGE | MODULE | UNCONDITIONAL); } /** Tells which class is performing the lookup. It is this class against * which checks are performed for visibility and access permissions. * <p>
*** 680,696 **** * The result is a bit-mask of the bits * {@linkplain #PUBLIC PUBLIC (0x01)}, * {@linkplain #PRIVATE PRIVATE (0x02)}, * {@linkplain #PROTECTED PROTECTED (0x04)}, * {@linkplain #PACKAGE PACKAGE (0x08)}, ! * and {@linkplain #MODULE MODULE (0x10)}. * <p> * A freshly-created lookup object ! * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} ! * has all possible bits set, since the caller class can access all its own members, ! * all public types in the caller's module, and all public types in packages exported ! * by other modules to the caller's module. * A lookup object on a new lookup class * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object} * may have some mode bits set to zero. * Mode bits can also be * {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}. --- 697,714 ---- * The result is a bit-mask of the bits * {@linkplain #PUBLIC PUBLIC (0x01)}, * {@linkplain #PRIVATE PRIVATE (0x02)}, * {@linkplain #PROTECTED PROTECTED (0x04)}, * {@linkplain #PACKAGE PACKAGE (0x08)}, ! * {@linkplain #MODULE MODULE (0x10)}, ! * and {@linkplain #UNCONDITIONAL UNCONDITIONAL (0x20)}. * <p> * A freshly-created lookup object ! * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has ! * all possible bits set, except {@code UNCONDITIONAL}. The lookup can be used to ! * access all members of the caller's class, all public types in the caller's module, ! * and all public types in packages exported by other modules to the caller's module. * A lookup object on a new lookup class * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object} * may have some mode bits set to zero. * Mode bits can also be * {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}.
*** 699,708 **** --- 717,729 ---- * so that it can access only names which can be reached by the original * lookup object, and also by the new lookup class. * @return the lookup modes, which limit the kinds of access performed by this lookup object * @see #in * @see #dropLookupMode + * + * @revised 9 + * @spec JPMS */ public int lookupModes() { return allowedModes & ALL_MODES; }
*** 710,722 **** * for method handle creation. * Must be called by from a method in this package, * which in turn is called by a method not in this package. */ Lookup(Class<?> lookupClass) { ! this(lookupClass, ALL_MODES); // make sure we haven't accidentally picked up a privileged class: ! checkUnprivilegedlookupClass(lookupClass, ALL_MODES); } private Lookup(Class<?> lookupClass, int allowedModes) { this.lookupClass = lookupClass; this.allowedModes = allowedModes; --- 731,743 ---- * for method handle creation. * Must be called by from a method in this package, * which in turn is called by a method not in this package. */ Lookup(Class<?> lookupClass) { ! this(lookupClass, FULL_POWER_MODES); // make sure we haven't accidentally picked up a privileged class: ! checkUnprivilegedlookupClass(lookupClass, FULL_POWER_MODES); } private Lookup(Class<?> lookupClass, int allowedModes) { this.lookupClass = lookupClass; this.allowedModes = allowedModes;
*** 728,750 **** * class as its own {@link #lookupClass lookupClass}. * <p> * However, the resulting {@code Lookup} object is guaranteed * to have no more access capabilities than the original. * In particular, access capabilities can be lost as follows:<ul> ! * <li>If the lookup class for this {@code Lookup} is not in a named module, ! * and the new lookup class is in a named module {@code M}, then no members in ! * {@code M}'s non-exported packages will be accessible. ! * <li>If the lookup for this {@code Lookup} is in a named module, and the ! * new lookup class is in a different module {@code M}, then no members, not even ! * public members in {@code M}'s exported packages, will be accessible. ! * <li>If the new lookup class differs from the old one, ! * protected members will not be accessible by virtue of inheritance. ! * (Protected members may continue to be accessible because of package sharing.) * <li>If the new lookup class is in a different package * than the old one, protected and default (package) members will not be accessible. * <li>If the new lookup class is not within the same package member ! * as the old one, private members will not be accessible. * <li>If the new lookup class is not accessible to the old lookup class, * then no members, not even public members, will be accessible. * (In all other cases, public members will continue to be accessible.) * </ul> * <p> --- 749,772 ---- * class as its own {@link #lookupClass lookupClass}. * <p> * However, the resulting {@code Lookup} object is guaranteed * to have no more access capabilities than the original. * In particular, access capabilities can be lost as follows:<ul> ! * <li>If the old lookup class is in a {@link Module#isNamed() named} module, and ! * the new lookup class is in a different module {@code M}, then no members, not ! * even public members in {@code M}'s exported packages, will be accessible. ! * The exception to this is when this lookup is {@link #publicLookup() ! * publicLookup}, in which case {@code PUBLIC} access is not lost. ! * <li>If the old lookup class is in an unnamed module, and the new lookup class ! * is a different module then {@link #MODULE MODULE} access is lost. ! * <li>If the new lookup class differs from the old one then {@code UNCONDITIONAL} is lost. * <li>If the new lookup class is in a different package * than the old one, protected and default (package) members will not be accessible. * <li>If the new lookup class is not within the same package member ! * as the old one, private members will not be accessible, and protected members ! * will not be accessible by virtue of inheritance. ! * (Protected members may continue to be accessible because of package sharing.) * <li>If the new lookup class is not accessible to the old lookup class, * then no members, not even public members, will be accessible. * (In all other cases, public members will continue to be accessible.) * </ul> * <p>
*** 755,790 **** * * @param requestedLookupClass the desired lookup class for the new lookup object * @return a lookup object which reports the desired lookup class, or the same object * if there is no change * @throws NullPointerException if the argument is null */ public Lookup in(Class<?> requestedLookupClass) { Objects.requireNonNull(requestedLookupClass); if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all ! return new Lookup(requestedLookupClass, ALL_MODES); if (requestedLookupClass == this.lookupClass) return this; // keep same capabilities ! ! int newModes = (allowedModes & (ALL_MODES & ~PROTECTED)); if (!VerifyAccess.isSameModule(this.lookupClass, requestedLookupClass)) { ! // Allowed to teleport from an unnamed to a named module but resulting ! // Lookup has no access to module private members ! if (this.lookupClass.getModule().isNamed()) { newModes = 0; ! } else { ! newModes &= ~MODULE; ! } } if ((newModes & PACKAGE) != 0 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) { ! newModes &= ~(PACKAGE|PRIVATE); } // Allow nestmate lookups to be created without special privilege: if ((newModes & PRIVATE) != 0 && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) { ! newModes &= ~PRIVATE; } if ((newModes & PUBLIC) != 0 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) { // The requested class it not accessible from the lookup class. // No permissions. --- 777,814 ---- * * @param requestedLookupClass the desired lookup class for the new lookup object * @return a lookup object which reports the desired lookup class, or the same object * if there is no change * @throws NullPointerException if the argument is null + * + * @revised 9 + * @spec JPMS */ public Lookup in(Class<?> requestedLookupClass) { Objects.requireNonNull(requestedLookupClass); if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all ! return new Lookup(requestedLookupClass, FULL_POWER_MODES); if (requestedLookupClass == this.lookupClass) return this; // keep same capabilities ! int newModes = (allowedModes & FULL_POWER_MODES); if (!VerifyAccess.isSameModule(this.lookupClass, requestedLookupClass)) { ! // Need to drop all access when teleporting from a named module to another ! // module. The exception is publicLookup where PUBLIC is not lost. ! if (this.lookupClass.getModule().isNamed() ! && (this.allowedModes & UNCONDITIONAL) == 0) newModes = 0; ! else ! newModes &= ~(MODULE|PACKAGE|PRIVATE|PROTECTED); } if ((newModes & PACKAGE) != 0 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) { ! newModes &= ~(PACKAGE|PRIVATE|PROTECTED); } // Allow nestmate lookups to be created without special privilege: if ((newModes & PRIVATE) != 0 && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) { ! newModes &= ~(PRIVATE|PROTECTED); } if ((newModes & PUBLIC) != 0 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) { // The requested class it not accessible from the lookup class. // No permissions.
*** 799,830 **** /** * Creates a lookup on the same lookup class which this lookup object * finds members, but with a lookup mode that has lost the given lookup mode. * The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE * MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED} or {@link #PRIVATE PRIVATE}. ! * {@link #PROTECTED PROTECTED} is always dropped and so the resulting lookup ! * mode will never have this access capability. When dropping {@code PACKAGE} ! * then the resulting lookup will not have {@code PACKAGE} or {@code PRIVATE} ! * access. When dropping {@code MODULE} then the resulting lookup will not ! * have {@code MODULE}, {@code PACKAGE}, or {@code PRIVATE} access. If {@code ! * PUBLIC} is dropped then the resulting lookup has no access. * @param modeToDrop the lookup mode to drop * @return a lookup object which lacks the indicated mode, or the same object if there is no change * @throws IllegalArgumentException if {@code modeToDrop} is not one of {@code PUBLIC}, ! * {@code MODULE}, {@code PACKAGE}, {@code PROTECTED} or {@code PRIVATE} ! * @since 9 * @see MethodHandles#privateLookupIn */ public Lookup dropLookupMode(int modeToDrop) { int oldModes = lookupModes(); ! int newModes = oldModes & ~(modeToDrop | PROTECTED); switch (modeToDrop) { case PUBLIC: newModes &= ~(ALL_MODES); break; case MODULE: newModes &= ~(PACKAGE | PRIVATE); break; case PACKAGE: newModes &= ~(PRIVATE); break; case PROTECTED: ! case PRIVATE: break; default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop"); } if (newModes == oldModes) return this; // return self if no change return new Lookup(lookupClass(), newModes); } --- 823,855 ---- /** * Creates a lookup on the same lookup class which this lookup object * finds members, but with a lookup mode that has lost the given lookup mode. * The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE * MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED} or {@link #PRIVATE PRIVATE}. ! * {@link #PROTECTED PROTECTED} and {@link #UNCONDITIONAL UNCONDITIONAL} are always ! * dropped and so the resulting lookup mode will never have these access capabilities. ! * When dropping {@code PACKAGE} then the resulting lookup will not have {@code PACKAGE} ! * or {@code PRIVATE} access. When dropping {@code MODULE} then the resulting lookup will ! * not have {@code MODULE}, {@code PACKAGE}, or {@code PRIVATE} access. If {@code PUBLIC} ! * is dropped then the resulting lookup has no access. * @param modeToDrop the lookup mode to drop * @return a lookup object which lacks the indicated mode, or the same object if there is no change * @throws IllegalArgumentException if {@code modeToDrop} is not one of {@code PUBLIC}, ! * {@code MODULE}, {@code PACKAGE}, {@code PROTECTED}, {@code PRIVATE} or {@code UNCONDITIONAL} * @see MethodHandles#privateLookupIn + * @since 9 */ public Lookup dropLookupMode(int modeToDrop) { int oldModes = lookupModes(); ! int newModes = oldModes & ~(modeToDrop | PROTECTED | UNCONDITIONAL); switch (modeToDrop) { case PUBLIC: newModes &= ~(ALL_MODES); break; case MODULE: newModes &= ~(PACKAGE | PRIVATE); break; case PACKAGE: newModes &= ~(PRIVATE); break; case PROTECTED: ! case PRIVATE: ! case UNCONDITIONAL: break; default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop"); } if (newModes == oldModes) return this; // return self if no change return new Lookup(lookupClass(), newModes); }
*** 833,853 **** static { IMPL_NAMES.getClass(); } /** Package-private version of lookup which is trusted. */ static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED); private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) { String name = lookupClass.getName(); if (name.startsWith("java.lang.invoke.")) throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); // For caller-sensitive MethodHandles.lookup() disallow lookup from // restricted packages. This a fragile and blunt approach. // TODO replace with a more formal and less fragile mechanism // that does not bluntly restrict classes under packages within // java.base from looking up MethodHandles or VarHandles. ! if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) { if ((name.startsWith("java.") && !name.equals("java.lang.Thread") && !name.startsWith("java.util.concurrent.")) || (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) { --- 858,884 ---- static { IMPL_NAMES.getClass(); } /** Package-private version of lookup which is trusted. */ static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED); + /** Version of lookup which is trusted minimally. + * It can only be used to create method handles to publicly accessible + * members in packages that are exported unconditionally. + */ + static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, (PUBLIC|UNCONDITIONAL)); + private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) { String name = lookupClass.getName(); if (name.startsWith("java.lang.invoke.")) throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); // For caller-sensitive MethodHandles.lookup() disallow lookup from // restricted packages. This a fragile and blunt approach. // TODO replace with a more formal and less fragile mechanism // that does not bluntly restrict classes under packages within // java.base from looking up MethodHandles or VarHandles. ! if (allowedModes == FULL_POWER_MODES && lookupClass.getClassLoader() == null) { if ((name.startsWith("java.") && !name.equals("java.lang.Thread") && !name.startsWith("java.util.concurrent.")) || (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) {
*** 864,873 **** --- 895,905 ---- * of a slash and a keyword. The keyword represents the strongest * allowed access, and is chosen as follows: * <ul> * <li>If no access is allowed, the suffix is "/noaccess". * <li>If only public access to types in exported packages is allowed, the suffix is "/public". + * <li>If only public access and unconditional access are allowed, the suffix is "/publicLookup". * <li>If only public and module access are allowed, the suffix is "/module". * <li>If only public, module and package access are allowed, the suffix is "/package". * <li>If only public, module, package, and private access are allowed, the suffix is "/private". * </ul> * If none of the above cases apply, it is the case that full
*** 882,907 **** * stronger than private access. Viewed independently from * package access, protected access is the first to be lost, * because it requires a direct subclass relationship between * caller and callee.) * @see #in */ @Override public String toString() { String cname = lookupClass.getName(); switch (allowedModes) { case 0: // no privileges return cname + "/noaccess"; case PUBLIC: return cname + "/public"; case PUBLIC|MODULE: return cname + "/module"; case PUBLIC|MODULE|PACKAGE: return cname + "/package"; ! case ALL_MODES & ~PROTECTED: return cname + "/private"; ! case ALL_MODES: return cname; case TRUSTED: return "/trusted"; // internal only; not exported default: // Should not happen, but it's a bitfield... cname = cname + "/" + Integer.toHexString(allowedModes); --- 914,944 ---- * stronger than private access. Viewed independently from * package access, protected access is the first to be lost, * because it requires a direct subclass relationship between * caller and callee.) * @see #in + * + * @revised 9 + * @spec JPMS */ @Override public String toString() { String cname = lookupClass.getName(); switch (allowedModes) { case 0: // no privileges return cname + "/noaccess"; case PUBLIC: return cname + "/public"; + case PUBLIC|UNCONDITIONAL: + return cname + "/publicLookup"; case PUBLIC|MODULE: return cname + "/module"; case PUBLIC|MODULE|PACKAGE: return cname + "/package"; ! case FULL_POWER_MODES & ~PROTECTED: return cname + "/private"; ! case FULL_POWER_MODES: return cname; case TRUSTED: return "/trusted"; // internal only; not exported default: // Should not happen, but it's a bitfield... cname = cname + "/" + Integer.toHexString(allowedModes);
*** 1578,1587 **** --- 1615,1625 ---- MemberName method = new MemberName(m); byte refKind = method.getReferenceKind(); if (refKind == REF_invokeSpecial) refKind = REF_invokeVirtual; assert(method.isMethod()); + @SuppressWarnings("deprecation") Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method)); } private MethodHandle unreflectForMH(Method m) { // these names require special lookups because they throw UnsupportedOperationException
*** 1660,1669 **** --- 1698,1708 ---- * @throws NullPointerException if the argument is null */ public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException { MemberName ctor = new MemberName(c); assert(ctor.isConstructor()); + @SuppressWarnings("deprecation") Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this; return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor); } /**
*** 1690,1699 **** --- 1729,1739 ---- private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException { MemberName field = new MemberName(f, isSetter); assert(isSetter ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind()) : MethodHandleNatives.refKindIsGetter(field.getReferenceKind())); + @SuppressWarnings("deprecation") Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this; return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field); } /**
*** 2031,2043 **** // check the class first: boolean classOK = (Modifier.isPublic(defc.getModifiers()) && (defc == refc || Modifier.isPublic(refc.getModifiers()))); if (!classOK && (allowedModes & PACKAGE) != 0) { ! classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), ALL_MODES) && (defc == refc || ! VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES))); } if (!classOK) return "class is not public"; if (Modifier.isPublic(mods)) return "access to public member failed"; // (how?, module not readable?) --- 2071,2083 ---- // check the class first: boolean classOK = (Modifier.isPublic(defc.getModifiers()) && (defc == refc || Modifier.isPublic(refc.getModifiers()))); if (!classOK && (allowedModes & PACKAGE) != 0) { ! classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), FULL_POWER_MODES) && (defc == refc || ! VerifyAccess.isClassAccessible(refc, lookupClass(), FULL_POWER_MODES))); } if (!classOK) return "class is not public"; if (Modifier.isPublic(mods)) return "access to public member failed"; // (how?, module not readable?)
*** 2346,2402 **** static ConcurrentHashMap<MemberName, DirectMethodHandle> LOOKASIDE_TABLE = new ConcurrentHashMap<>(); } /** - * Helper class used to lazily create PUBLIC_LOOKUP with a lookup class - * in an <em>unnamed module</em>. - * - * @see Lookup#publicLookup - */ - private static class LookupHelper { - private static final String UNNAMED = "Unnamed"; - private static final String OBJECT = "java/lang/Object"; - - private static Class<?> createClass() { - try { - ClassWriter cw = new ClassWriter(0); - cw.visit(Opcodes.V1_8, - Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, - UNNAMED, - null, - OBJECT, - null); - cw.visitSource(UNNAMED, null); - cw.visitEnd(); - byte[] bytes = cw.toByteArray(); - ClassLoader loader = new ClassLoader(null) { - @Override - protected Class<?> findClass(String cn) throws ClassNotFoundException { - if (cn.equals(UNNAMED)) - return super.defineClass(UNNAMED, bytes, 0, bytes.length); - throw new ClassNotFoundException(cn); - } - }; - return loader.loadClass(UNNAMED); - } catch (Exception e) { - throw new InternalError(e); - } - } - - private static final Class<?> PUBLIC_LOOKUP_CLASS = createClass(); - - /** - * Lookup that is trusted minimally. It can only be used to create - * method handles to publicly accessible members in exported packages. - * - * @see MethodHandles#publicLookup - */ - static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_LOOKUP_CLASS, Lookup.PUBLIC); - } - - /** * Produces a method handle constructing arrays of a desired type. * The return type of the method handle will be the array type. * The type of its sole argument will be {@code int}, which specifies the size of the array. * @param arrayClass an array type * @return a method handle which can create arrays of the given type --- 2386,2395 ----
< prev index next >