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