< prev index next >

src/java.base/share/classes/java/lang/reflect/AccessibleObject.java

Print this page

        

*** 26,38 **** --- 26,41 ---- package java.lang.reflect; import java.lang.annotation.Annotation; import java.security.AccessController; + import jdk.internal.misc.VM; + import jdk.internal.module.IllegalAccessLogger; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.reflect.ReflectionFactory; + import sun.security.action.GetPropertyAction; /** * The {@code AccessibleObject} class is the base class for {@code Field}, * {@code Method}, and {@code Constructor} objects (known as <em>reflected * objects</em>). It provides the ability to flag a reflected object as
*** 286,328 **** if (callerModule == declaringModule) return true; if (callerModule == Object.class.getModule()) return true; if (!declaringModule.isNamed()) return true; ! // package is open to caller ! String pn = packageName(declaringClass); ! if (declaringModule.isOpen(pn, callerModule)) { ! dumpStackIfOpenedReflectively(declaringModule, pn, callerModule); ! return true; ! } ! ! // package is exported to caller ! boolean isExported = declaringModule.isExported(pn, callerModule); ! boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers()); int modifiers; if (this instanceof Executable) { modifiers = ((Executable) this).getModifiers(); } else { modifiers = ((Field) this).getModifiers(); } - if (isExported && isClassPublic) { // member is public if (Modifier.isPublic(modifiers)) { ! dumpStackIfExportedReflectively(declaringModule, pn, callerModule); return true; } // member is protected-static if (Modifier.isProtected(modifiers) && Modifier.isStatic(modifiers) && isSubclassOf(caller, declaringClass)) { ! dumpStackIfExportedReflectively(declaringModule, pn, callerModule); return true; } } if (throwExceptionIfDenied) { // not accessible String msg = "Unable to make "; if (this instanceof Field) msg += "field "; --- 289,330 ---- if (callerModule == declaringModule) return true; if (callerModule == Object.class.getModule()) return true; if (!declaringModule.isNamed()) return true; ! String pn = declaringClass.getPackageName(); int modifiers; if (this instanceof Executable) { modifiers = ((Executable) this).getModifiers(); } else { modifiers = ((Field) this).getModifiers(); } + // class is public and package is exported to caller + boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers()); + if (isClassPublic && declaringModule.isExported(pn, callerModule)) { // member is public if (Modifier.isPublic(modifiers)) { ! logIfExportedByBackdoor(caller, declaringClass); return true; } // member is protected-static if (Modifier.isProtected(modifiers) && Modifier.isStatic(modifiers) && isSubclassOf(caller, declaringClass)) { ! logIfExportedByBackdoor(caller, declaringClass); return true; } } + // package is open to caller + if (declaringModule.isOpen(pn, callerModule)) { + logIfOpenedByBackdoor(caller, declaringClass); + return true; + } + if (throwExceptionIfDenied) { // not accessible String msg = "Unable to make "; if (this instanceof Field) msg += "field ";
*** 331,341 **** msg += "exports"; else msg += "opens"; msg += " " + pn + "\" to " + callerModule; InaccessibleObjectException e = new InaccessibleObjectException(msg); ! if (Reflection.printStackTraceWhenAccessFails()) { e.printStackTrace(System.err); } throw e; } return false; --- 333,343 ---- msg += "exports"; else msg += "opens"; msg += " " + pn + "\" to " + callerModule; InaccessibleObjectException e = new InaccessibleObjectException(msg); ! if (printStackTraceWhenAccessFails()) { e.printStackTrace(System.err); } throw e; } return false;
*** 349,400 **** queryClass = queryClass.getSuperclass(); } return false; } ! private void dumpStackIfOpenedReflectively(Module module, ! String pn, ! Module other) { ! dumpStackIfExposedReflectively(module, pn, other, true); ! } ! ! private void dumpStackIfExportedReflectively(Module module, ! String pn, ! Module other) { ! dumpStackIfExposedReflectively(module, pn, other, false); ! } ! ! private void dumpStackIfExposedReflectively(Module module, ! String pn, ! Module other, ! boolean open) ! { ! if (Reflection.printStackTraceWhenAccessSucceeds() ! && !module.isStaticallyExportedOrOpen(pn, other, open)) ! { ! String msg = other + " allowed to invoke setAccessible on "; ! if (this instanceof Field) ! msg += "field "; ! msg += this; ! new Exception(msg) { ! private static final long serialVersionUID = 42L; ! public String toString() { ! return "WARNING: " + getMessage(); } - }.printStackTrace(System.err); } } /** ! * Returns the package name of the given class. */ ! private static String packageName(Class<?> c) { ! while (c.isArray()) { ! c = c.getComponentType(); ! } ! String pn = c.getPackageName(); ! return (pn != null) ? pn : ""; } /** * Get the value of the {@code accessible} flag for this reflected object. * --- 351,389 ---- queryClass = queryClass.getSuperclass(); } return false; } ! private void logIfOpenedByBackdoor(Class<?> caller, Class<?> declaringClass) { ! Module callerModule = caller.getModule(); ! Module targetModule = declaringClass.getModule(); ! // callerModule is null during early startup ! if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) { ! IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger(); ! if (logger != null) { ! logger.logIfOpenedByBackdoor(caller, declaringClass, this::toShortString); ! } ! } ! } ! ! private void logIfExportedByBackdoor(Class<?> caller, Class<?> declaringClass) { ! Module callerModule = caller.getModule(); ! Module targetModule = declaringClass.getModule(); ! // callerModule is null during early startup ! if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) { ! IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger(); ! if (logger != null) { ! logger.logIfExportedByBackdoor(caller, declaringClass, this::toShortString); } } } /** ! * Returns a short descriptive string to describe this object in log messages. */ ! String toShortString() { ! return toString(); } /** * Get the value of the {@code accessible} flag for this reflected object. *
*** 407,416 **** --- 396,406 ---- * This method may return {@code false} on a reflected object that is * accessible to the caller. To test if this reflected object is accessible, * it should use {@link #canAccess(Object)}. * * @revised 9 + * @spec JPMS */ @Deprecated(since="9") public boolean isAccessible() { return override; }
*** 481,494 **** if (this instanceof Constructor) { targetClass = declaringClass; } else { targetClass = Modifier.isStatic(modifiers) ? null : obj.getClass(); } ! return Reflection.verifyMemberAccess(caller, ! declaringClass, ! targetClass, ! modifiers); } /** * Constructor: only used by the Java Virtual Machine. */ --- 471,481 ---- if (this instanceof Constructor) { targetClass = declaringClass; } else { targetClass = Modifier.isStatic(modifiers) ? null : obj.getClass(); } ! return verifyAccess(caller, declaringClass, targetClass, modifiers); } /** * Constructor: only used by the Java Virtual Machine. */
*** 596,637 **** final void checkAccess(Class<?> caller, Class<?> memberClass, Class<?> targetClass, int modifiers) throws IllegalAccessException { if (caller == memberClass) { // quick check ! return; // ACCESS IS OK } Object cache = securityCheckCache; // read volatile if (targetClass != null // instance member or constructor && Modifier.isProtected(modifiers) && targetClass != memberClass) { // Must match a 2-list of { caller, targetClass }. if (cache instanceof Class[]) { Class<?>[] cache2 = (Class<?>[]) cache; if (cache2[1] == targetClass && cache2[0] == caller) { ! return; // ACCESS IS OK } // (Test cache[1] first since range check for [1] // subsumes range check for [0].) } } else if (cache == caller) { // Non-protected case (or targetClass == memberClass or static member). ! return; // ACCESS IS OK } // If no return, fall through to the slow path. ! slowCheckMemberAccess(caller, memberClass, targetClass, modifiers); } // Keep all this slow stuff out of line: ! void slowCheckMemberAccess(Class<?> caller, Class<?> memberClass, Class<?> targetClass, int modifiers) - throws IllegalAccessException { ! Reflection.ensureMemberAccess(caller, memberClass, targetClass, modifiers); // Success: Update the cache. Object cache = (targetClass != null && Modifier.isProtected(modifiers) && targetClass != memberClass) --- 583,642 ---- final void checkAccess(Class<?> caller, Class<?> memberClass, Class<?> targetClass, int modifiers) throws IllegalAccessException { + if (!verifyAccess(caller, memberClass, targetClass, modifiers)) { + IllegalAccessException e = Reflection.newIllegalAccessException( + caller, memberClass, targetClass, modifiers); + if (printStackTraceWhenAccessFails()) { + e.printStackTrace(System.err); + } + throw e; + } + } + + final boolean verifyAccess(Class<?> caller, Class<?> memberClass, + Class<?> targetClass, int modifiers) + { if (caller == memberClass) { // quick check ! return true; // ACCESS IS OK } Object cache = securityCheckCache; // read volatile if (targetClass != null // instance member or constructor && Modifier.isProtected(modifiers) && targetClass != memberClass) { // Must match a 2-list of { caller, targetClass }. if (cache instanceof Class[]) { Class<?>[] cache2 = (Class<?>[]) cache; if (cache2[1] == targetClass && cache2[0] == caller) { ! return true; // ACCESS IS OK } // (Test cache[1] first since range check for [1] // subsumes range check for [0].) } } else if (cache == caller) { // Non-protected case (or targetClass == memberClass or static member). ! return true; // ACCESS IS OK } // If no return, fall through to the slow path. ! return slowVerifyAccess(caller, memberClass, targetClass, modifiers); } // Keep all this slow stuff out of line: ! private boolean slowVerifyAccess(Class<?> caller, Class<?> memberClass, Class<?> targetClass, int modifiers) { ! if (!Reflection.verifyMemberAccess(caller, memberClass, targetClass, modifiers)) { ! // access denied ! return false; ! } ! ! // access okay ! logIfExportedByBackdoor(caller, memberClass); // Success: Update the cache. Object cache = (targetClass != null && Modifier.isProtected(modifiers) && targetClass != memberClass)
*** 641,647 **** --- 646,674 ---- // Note: The two cache elements are not volatile, // but they are effectively final. The Java memory model // guarantees that the initializing stores for the cache // elements will occur before the volatile write. securityCheckCache = cache; // write volatile + return true; + } + + // true to print a stack trace when access fails + private static volatile boolean printStackWhenAccessFails; + + // true if printStack* values are initialized + private static volatile boolean printStackPropertiesSet; + + /** + * Returns true if a stack trace should be printed when access fails. + */ + private static boolean printStackTraceWhenAccessFails() { + if (!printStackPropertiesSet && VM.initLevel() >= 1) { + String s = GetPropertyAction.privilegedGetProperty( + "sun.reflect.debugModuleAccessChecks"); + if (s != null) { + printStackWhenAccessFails = !s.equalsIgnoreCase("false"); + } + printStackPropertiesSet = true; + } + return printStackWhenAccessFails; } }
< prev index next >