jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
changeset 44359 c6761862ca0b
parent 43712 5dfd0950317c
child 45652 33342314ce89
equal deleted inserted replaced
44210:5a8499c4b32c 44359:c6761862ca0b
    26 package java.lang.reflect;
    26 package java.lang.reflect;
    27 
    27 
    28 import java.lang.annotation.Annotation;
    28 import java.lang.annotation.Annotation;
    29 import java.security.AccessController;
    29 import java.security.AccessController;
    30 
    30 
       
    31 import jdk.internal.misc.VM;
       
    32 import jdk.internal.module.IllegalAccessLogger;
    31 import jdk.internal.reflect.CallerSensitive;
    33 import jdk.internal.reflect.CallerSensitive;
    32 import jdk.internal.reflect.Reflection;
    34 import jdk.internal.reflect.Reflection;
    33 import jdk.internal.reflect.ReflectionFactory;
    35 import jdk.internal.reflect.ReflectionFactory;
       
    36 import sun.security.action.GetPropertyAction;
    34 
    37 
    35 /**
    38 /**
    36  * The {@code AccessibleObject} class is the base class for {@code Field},
    39  * The {@code AccessibleObject} class is the base class for {@code Field},
    37  * {@code Method}, and {@code Constructor} objects (known as <em>reflected
    40  * {@code Method}, and {@code Constructor} objects (known as <em>reflected
    38  * objects</em>). It provides the ability to flag a reflected object as
    41  * objects</em>). It provides the ability to flag a reflected object as
   286 
   289 
   287         if (callerModule == declaringModule) return true;
   290         if (callerModule == declaringModule) return true;
   288         if (callerModule == Object.class.getModule()) return true;
   291         if (callerModule == Object.class.getModule()) return true;
   289         if (!declaringModule.isNamed()) return true;
   292         if (!declaringModule.isNamed()) return true;
   290 
   293 
   291         // package is open to caller
   294         String pn = declaringClass.getPackageName();
   292         String pn = packageName(declaringClass);
       
   293         if (declaringModule.isOpen(pn, callerModule)) {
       
   294             dumpStackIfOpenedReflectively(declaringModule, pn, callerModule);
       
   295             return true;
       
   296         }
       
   297 
       
   298         // package is exported to caller
       
   299         boolean isExported = declaringModule.isExported(pn, callerModule);
       
   300         boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers());
       
   301         int modifiers;
   295         int modifiers;
   302         if (this instanceof Executable) {
   296         if (this instanceof Executable) {
   303             modifiers = ((Executable) this).getModifiers();
   297             modifiers = ((Executable) this).getModifiers();
   304         } else {
   298         } else {
   305             modifiers = ((Field) this).getModifiers();
   299             modifiers = ((Field) this).getModifiers();
   306         }
   300         }
   307         if (isExported && isClassPublic) {
   301 
   308 
   302         // class is public and package is exported to caller
       
   303         boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers());
       
   304         if (isClassPublic && declaringModule.isExported(pn, callerModule)) {
   309             // member is public
   305             // member is public
   310             if (Modifier.isPublic(modifiers)) {
   306             if (Modifier.isPublic(modifiers)) {
   311                 dumpStackIfExportedReflectively(declaringModule, pn, callerModule);
   307                 logIfExportedByBackdoor(caller, declaringClass);
   312                 return true;
   308                 return true;
   313             }
   309             }
   314 
   310 
   315             // member is protected-static
   311             // member is protected-static
   316             if (Modifier.isProtected(modifiers)
   312             if (Modifier.isProtected(modifiers)
   317                 && Modifier.isStatic(modifiers)
   313                 && Modifier.isStatic(modifiers)
   318                 && isSubclassOf(caller, declaringClass)) {
   314                 && isSubclassOf(caller, declaringClass)) {
   319                 dumpStackIfExportedReflectively(declaringModule, pn, callerModule);
   315                 logIfExportedByBackdoor(caller, declaringClass);
   320                 return true;
   316                 return true;
   321             }
   317             }
       
   318         }
       
   319 
       
   320         // package is open to caller
       
   321         if (declaringModule.isOpen(pn, callerModule)) {
       
   322             logIfOpenedByBackdoor(caller, declaringClass);
       
   323             return true;
   322         }
   324         }
   323 
   325 
   324         if (throwExceptionIfDenied) {
   326         if (throwExceptionIfDenied) {
   325             // not accessible
   327             // not accessible
   326             String msg = "Unable to make ";
   328             String msg = "Unable to make ";
   331                 msg += "exports";
   333                 msg += "exports";
   332             else
   334             else
   333                 msg += "opens";
   335                 msg += "opens";
   334             msg += " " + pn + "\" to " + callerModule;
   336             msg += " " + pn + "\" to " + callerModule;
   335             InaccessibleObjectException e = new InaccessibleObjectException(msg);
   337             InaccessibleObjectException e = new InaccessibleObjectException(msg);
   336             if (Reflection.printStackTraceWhenAccessFails()) {
   338             if (printStackTraceWhenAccessFails()) {
   337                 e.printStackTrace(System.err);
   339                 e.printStackTrace(System.err);
   338             }
   340             }
   339             throw e;
   341             throw e;
   340         }
   342         }
   341         return false;
   343         return false;
   349             queryClass = queryClass.getSuperclass();
   351             queryClass = queryClass.getSuperclass();
   350         }
   352         }
   351         return false;
   353         return false;
   352     }
   354     }
   353 
   355 
   354     private void dumpStackIfOpenedReflectively(Module module,
   356     private void logIfOpenedByBackdoor(Class<?> caller, Class<?> declaringClass) {
   355                                                String pn,
   357         Module callerModule = caller.getModule();
   356                                                Module other) {
   358         Module targetModule = declaringClass.getModule();
   357         dumpStackIfExposedReflectively(module, pn, other, true);
   359         // callerModule is null during early startup
   358     }
   360         if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) {
   359 
   361             IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
   360     private void dumpStackIfExportedReflectively(Module module,
   362             if (logger != null) {
   361                                                  String pn,
   363                 logger.logIfOpenedByBackdoor(caller, declaringClass, this::toShortString);
   362                                                  Module other) {
   364             }
   363         dumpStackIfExposedReflectively(module, pn, other, false);
   365         }
   364     }
   366     }
   365 
   367 
   366     private void dumpStackIfExposedReflectively(Module module,
   368     private void logIfExportedByBackdoor(Class<?> caller, Class<?> declaringClass) {
   367                                                 String pn,
   369         Module callerModule = caller.getModule();
   368                                                 Module other,
   370         Module targetModule = declaringClass.getModule();
   369                                                 boolean open)
   371         // callerModule is null during early startup
   370     {
   372         if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) {
   371         if (Reflection.printStackTraceWhenAccessSucceeds()
   373             IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
   372                 && !module.isStaticallyExportedOrOpen(pn, other, open))
   374             if (logger != null) {
   373         {
   375                 logger.logIfExportedByBackdoor(caller, declaringClass, this::toShortString);
   374             String msg = other + " allowed to invoke setAccessible on ";
   376             }
   375             if (this instanceof Field)
   377         }
   376                 msg += "field ";
   378     }
   377             msg += this;
   379 
   378             new Exception(msg) {
   380     /**
   379                 private static final long serialVersionUID = 42L;
   381      * Returns a short descriptive string to describe this object in log messages.
   380                 public String toString() {
   382      */
   381                     return "WARNING: " + getMessage();
   383     String toShortString() {
   382                 }
   384         return toString();
   383             }.printStackTrace(System.err);
       
   384         }
       
   385     }
       
   386 
       
   387     /**
       
   388      * Returns the package name of the given class.
       
   389      */
       
   390     private static String packageName(Class<?> c) {
       
   391         while (c.isArray()) {
       
   392             c = c.getComponentType();
       
   393         }
       
   394         String pn = c.getPackageName();
       
   395         return (pn != null) ? pn : "";
       
   396     }
   385     }
   397 
   386 
   398     /**
   387     /**
   399      * Get the value of the {@code accessible} flag for this reflected object.
   388      * Get the value of the {@code accessible} flag for this reflected object.
   400      *
   389      *
   407      * This method may return {@code false} on a reflected object that is
   396      * This method may return {@code false} on a reflected object that is
   408      * accessible to the caller. To test if this reflected object is accessible,
   397      * accessible to the caller. To test if this reflected object is accessible,
   409      * it should use {@link #canAccess(Object)}.
   398      * it should use {@link #canAccess(Object)}.
   410      *
   399      *
   411      * @revised 9
   400      * @revised 9
       
   401      * @spec JPMS
   412      */
   402      */
   413     @Deprecated(since="9")
   403     @Deprecated(since="9")
   414     public boolean isAccessible() {
   404     public boolean isAccessible() {
   415         return override;
   405         return override;
   416     }
   406     }
   481         if (this instanceof Constructor) {
   471         if (this instanceof Constructor) {
   482             targetClass = declaringClass;
   472             targetClass = declaringClass;
   483         } else {
   473         } else {
   484             targetClass = Modifier.isStatic(modifiers) ? null : obj.getClass();
   474             targetClass = Modifier.isStatic(modifiers) ? null : obj.getClass();
   485         }
   475         }
   486         return Reflection.verifyMemberAccess(caller,
   476         return verifyAccess(caller, declaringClass, targetClass, modifiers);
   487                                              declaringClass,
       
   488                                              targetClass,
       
   489                                              modifiers);
       
   490     }
   477     }
   491 
   478 
   492     /**
   479     /**
   493      * Constructor: only used by the Java Virtual Machine.
   480      * Constructor: only used by the Java Virtual Machine.
   494      */
   481      */
   525     @Override
   512     @Override
   526     public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
   513     public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
   527         return AnnotatedElement.super.isAnnotationPresent(annotationClass);
   514         return AnnotatedElement.super.isAnnotationPresent(annotationClass);
   528     }
   515     }
   529 
   516 
   530    /**
   517     /**
   531      * @throws NullPointerException {@inheritDoc}
   518      * @throws NullPointerException {@inheritDoc}
   532      * @since 1.8
   519      * @since 1.8
   533      */
   520      */
   534     @Override
   521     @Override
   535     public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
   522     public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
   596 
   583 
   597     final void checkAccess(Class<?> caller, Class<?> memberClass,
   584     final void checkAccess(Class<?> caller, Class<?> memberClass,
   598                            Class<?> targetClass, int modifiers)
   585                            Class<?> targetClass, int modifiers)
   599         throws IllegalAccessException
   586         throws IllegalAccessException
   600     {
   587     {
       
   588         if (!verifyAccess(caller, memberClass, targetClass, modifiers)) {
       
   589             IllegalAccessException e = Reflection.newIllegalAccessException(
       
   590                 caller, memberClass, targetClass, modifiers);
       
   591             if (printStackTraceWhenAccessFails()) {
       
   592                 e.printStackTrace(System.err);
       
   593             }
       
   594             throw e;
       
   595         }
       
   596     }
       
   597 
       
   598     final boolean verifyAccess(Class<?> caller, Class<?> memberClass,
       
   599                                Class<?> targetClass, int modifiers)
       
   600     {
   601         if (caller == memberClass) {  // quick check
   601         if (caller == memberClass) {  // quick check
   602             return;             // ACCESS IS OK
   602             return true;             // ACCESS IS OK
   603         }
   603         }
   604         Object cache = securityCheckCache;  // read volatile
   604         Object cache = securityCheckCache;  // read volatile
   605         if (targetClass != null // instance member or constructor
   605         if (targetClass != null // instance member or constructor
   606             && Modifier.isProtected(modifiers)
   606             && Modifier.isProtected(modifiers)
   607             && targetClass != memberClass) {
   607             && targetClass != memberClass) {
   608             // Must match a 2-list of { caller, targetClass }.
   608             // Must match a 2-list of { caller, targetClass }.
   609             if (cache instanceof Class[]) {
   609             if (cache instanceof Class[]) {
   610                 Class<?>[] cache2 = (Class<?>[]) cache;
   610                 Class<?>[] cache2 = (Class<?>[]) cache;
   611                 if (cache2[1] == targetClass &&
   611                 if (cache2[1] == targetClass &&
   612                     cache2[0] == caller) {
   612                     cache2[0] == caller) {
   613                     return;     // ACCESS IS OK
   613                     return true;     // ACCESS IS OK
   614                 }
   614                 }
   615                 // (Test cache[1] first since range check for [1]
   615                 // (Test cache[1] first since range check for [1]
   616                 // subsumes range check for [0].)
   616                 // subsumes range check for [0].)
   617             }
   617             }
   618         } else if (cache == caller) {
   618         } else if (cache == caller) {
   619             // Non-protected case (or targetClass == memberClass or static member).
   619             // Non-protected case (or targetClass == memberClass or static member).
   620             return;             // ACCESS IS OK
   620             return true;             // ACCESS IS OK
   621         }
   621         }
   622 
   622 
   623         // If no return, fall through to the slow path.
   623         // If no return, fall through to the slow path.
   624         slowCheckMemberAccess(caller, memberClass, targetClass, modifiers);
   624         return slowVerifyAccess(caller, memberClass, targetClass, modifiers);
   625     }
   625     }
   626 
   626 
   627     // Keep all this slow stuff out of line:
   627     // Keep all this slow stuff out of line:
   628     void slowCheckMemberAccess(Class<?> caller, Class<?> memberClass,
   628     private boolean slowVerifyAccess(Class<?> caller, Class<?> memberClass,
   629                                Class<?> targetClass, int modifiers)
   629                                      Class<?> targetClass, int modifiers)
   630         throws IllegalAccessException
       
   631     {
   630     {
   632         Reflection.ensureMemberAccess(caller, memberClass, targetClass, modifiers);
   631         if (!Reflection.verifyMemberAccess(caller, memberClass, targetClass, modifiers)) {
       
   632             // access denied
       
   633             return false;
       
   634         }
       
   635 
       
   636         // access okay
       
   637         logIfExportedByBackdoor(caller, memberClass);
   633 
   638 
   634         // Success: Update the cache.
   639         // Success: Update the cache.
   635         Object cache = (targetClass != null
   640         Object cache = (targetClass != null
   636                         && Modifier.isProtected(modifiers)
   641                         && Modifier.isProtected(modifiers)
   637                         && targetClass != memberClass)
   642                         && targetClass != memberClass)
   641         // Note:  The two cache elements are not volatile,
   646         // Note:  The two cache elements are not volatile,
   642         // but they are effectively final.  The Java memory model
   647         // but they are effectively final.  The Java memory model
   643         // guarantees that the initializing stores for the cache
   648         // guarantees that the initializing stores for the cache
   644         // elements will occur before the volatile write.
   649         // elements will occur before the volatile write.
   645         securityCheckCache = cache;         // write volatile
   650         securityCheckCache = cache;         // write volatile
       
   651         return true;
       
   652     }
       
   653 
       
   654     // true to print a stack trace when access fails
       
   655     private static volatile boolean printStackWhenAccessFails;
       
   656 
       
   657     // true if printStack* values are initialized
       
   658     private static volatile boolean printStackPropertiesSet;
       
   659 
       
   660     /**
       
   661      * Returns true if a stack trace should be printed when access fails.
       
   662      */
       
   663     private static boolean printStackTraceWhenAccessFails() {
       
   664         if (!printStackPropertiesSet && VM.initLevel() >= 1) {
       
   665             String s = GetPropertyAction.privilegedGetProperty(
       
   666                     "sun.reflect.debugModuleAccessChecks");
       
   667             if (s != null) {
       
   668                 printStackWhenAccessFails = !s.equalsIgnoreCase("false");
       
   669             }
       
   670             printStackPropertiesSet = true;
       
   671         }
       
   672         return printStackWhenAccessFails;
   646     }
   673     }
   647 }
   674 }