< prev index next >

src/java.base/share/classes/jdk/internal/reflect/Reflection.java

Print this page




  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.internal.reflect;
  27 
  28 
  29 import java.lang.reflect.*;
  30 import java.util.HashMap;
  31 import java.util.Map;
  32 import java.util.Objects;
  33 import jdk.internal.HotSpotIntrinsicCandidate;
  34 import jdk.internal.misc.SharedSecrets;
  35 import jdk.internal.misc.VM;
  36 import sun.security.action.GetPropertyAction;
  37 
  38 /** Common utility routines used by both java.lang and
  39     java.lang.reflect */
  40 
  41 public class Reflection {
  42 
  43     /** Used to filter out fields and methods from certain classes from public
  44         view, where they are sensitive or they may contain VM-internal objects.
  45         These Maps are updated very rarely. Rather than synchronize on
  46         each access, we use copy-on-write */
  47     private static volatile Map<Class<?>,String[]> fieldFilterMap;
  48     private static volatile Map<Class<?>,String[]> methodFilterMap;
  49 
  50     static {
  51         Map<Class<?>,String[]> map = new HashMap<Class<?>,String[]>();
  52         map.put(Reflection.class,
  53             new String[] {"fieldFilterMap", "methodFilterMap"});
  54         map.put(System.class, new String[] {"security"});
  55         map.put(Class.class, new String[] {"classLoader"});
  56         fieldFilterMap = map;


  87 
  88     /**
  89      * Ensures that access to a member is granted and throws
  90      * IllegalAccessException if not.
  91      *
  92      * @param currentClass the class performing the access
  93      * @param memberClass the declaring class of the member being accessed
  94      * @param targetClass the class of target object if accessing instance
  95      *                    field or method;
  96      *                    or the declaring class if accessing constructor;
  97      *                    or null if accessing static field or method
  98      * @param modifiers the member's access modifiers
  99      * @throws IllegalAccessException if access to member is denied
 100      */
 101     public static void ensureMemberAccess(Class<?> currentClass,
 102                                           Class<?> memberClass,
 103                                           Class<?> targetClass,
 104                                           int modifiers)
 105         throws IllegalAccessException
 106     {
 107         if (currentClass == null || memberClass == null) {
 108             throw new InternalError();
 109         }
 110 
 111         if (!verifyMemberAccess(currentClass, memberClass, targetClass, modifiers)) {
 112             throwIllegalAccessException(currentClass, memberClass, targetClass, modifiers);
 113         }
 114     }
 115 
 116     /**
 117      * Verify access to a member, returning {@code false} if no access









 118      */
 119     public static boolean verifyMemberAccess(Class<?> currentClass,
 120                                              Class<?> memberClass,
 121                                              Class<?> targetClass,
 122                                              int modifiers)
 123     {
 124         // Verify that currentClass can access a field, method, or
 125         // constructor of memberClass, where that member's access bits are
 126         // "modifiers".
 127 
 128         boolean gotIsSameClassPackage = false;
 129         boolean isSameClassPackage = false;
 130 
 131         if (currentClass == memberClass) {
 132             // Always succeeds
 133             return true;
 134         }
 135 
 136         if (!verifyModuleAccess(currentClass, memberClass)) {
 137             return false;
 138         }
 139 



 140         if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {
 141             isSameClassPackage = isSameClassPackage(currentClass, memberClass);
 142             gotIsSameClassPackage = true;
 143             if (!isSameClassPackage) {
 144                 return false;
 145             }
 146         }
 147 
 148         // At this point we know that currentClass can access memberClass.
 149 
 150         if (Modifier.isPublic(modifiers)) {
 151             return true;
 152         }
 153 
 154         boolean successSoFar = false;
 155 
 156         if (Modifier.isProtected(modifiers)) {
 157             // See if currentClass is a subclass of memberClass
 158             if (isSubclassOf(currentClass, memberClass)) {
 159                 successSoFar = true;


 179         // Additional test for protected instance members
 180         // and protected constructors: JLS 6.6.2
 181         if (targetClass != null && Modifier.isProtected(modifiers) &&
 182             targetClass != currentClass)
 183         {
 184             if (!gotIsSameClassPackage) {
 185                 isSameClassPackage = isSameClassPackage(currentClass, memberClass);
 186                 gotIsSameClassPackage = true;
 187             }
 188             if (!isSameClassPackage) {
 189                 if (!isSubclassOf(targetClass, currentClass)) {
 190                     return false;
 191                 }
 192             }
 193         }
 194 
 195         return true;
 196     }
 197 
 198     /**
 199      * Returns {@code true} if memberClass's's module exports memberClass's
 200      * package to currentClass's module.
 201      */
 202     public static boolean verifyModuleAccess(Class<?> currentClass,
 203                                              Class<?> memberClass) {
 204         return verifyModuleAccess(currentClass.getModule(), memberClass);
 205     }
 206 
 207     public static boolean verifyModuleAccess(Module currentModule, Class<?> memberClass) {
 208         Module memberModule = memberClass.getModule();
 209 
 210         // module may be null during startup (initLevel 0)
 211         if (currentModule == memberModule)
 212            return true;  // same module (named or unnamed)
 213 

 214         String pkg = memberClass.getPackageName();
 215         boolean allowed = memberModule.isExported(pkg, currentModule);
 216         if (allowed && memberModule.isNamed() && printStackTraceWhenAccessSucceeds()) {
 217             if (!SharedSecrets.getJavaLangReflectModuleAccess()
 218                     .isStaticallyExported(memberModule, pkg, currentModule)) {
 219                 String msg = currentModule + " allowed access to member of " + memberClass;
 220                 new Exception(msg).printStackTrace(System.err);
 221             }
 222         }
 223         return allowed;
 224     }
 225 
 226     /**
 227      * Returns true if two classes in the same package.
 228      */
 229     private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
 230         if (c1.getClassLoader() != c2.getClassLoader())
 231             return false;
 232         return Objects.equals(c1.getPackageName(), c2.getPackageName());
 233     }
 234 
 235     static boolean isSubclassOf(Class<?> queryClass,
 236                                 Class<?> ofClass)
 237     {
 238         while (queryClass != null) {
 239             if (queryClass == ofClass) {
 240                 return true;
 241             }
 242             queryClass = queryClass.getSuperclass();
 243         }


 327      */
 328     public static boolean isCallerSensitive(Method m) {
 329         final ClassLoader loader = m.getDeclaringClass().getClassLoader();
 330         if (VM.isSystemDomainLoader(loader) || isExtClassLoader(loader))  {
 331             return m.isAnnotationPresent(CallerSensitive.class);
 332         }
 333         return false;
 334     }
 335 
 336     private static boolean isExtClassLoader(ClassLoader loader) {
 337         ClassLoader cl = ClassLoader.getSystemClassLoader();
 338         while (cl != null) {
 339             if (cl.getParent() == null && cl == loader) {
 340                 return true;
 341             }
 342             cl = cl.getParent();
 343         }
 344         return false;
 345     }
 346 
 347 
 348     // true to print a stack trace when access fails
 349     private static volatile boolean printStackWhenAccessFails;
 350 
 351     // true to print a stack trace when access succeeds
 352     private static volatile boolean printStackWhenAccessSucceeds;
 353 
 354     // true if printStack* values are initialized
 355     private static volatile boolean printStackPropertiesSet;
 356 
 357     private static void ensurePrintStackPropertiesSet() {
 358         if (!printStackPropertiesSet && VM.initLevel() >= 1) {
 359             String s = GetPropertyAction.privilegedGetProperty(
 360                     "sun.reflect.debugModuleAccessChecks");
 361             if (s != null) {
 362                 printStackWhenAccessFails = !s.equalsIgnoreCase("false");
 363                 printStackWhenAccessSucceeds = s.equalsIgnoreCase("access");
 364             }
 365             printStackPropertiesSet = true;
 366         }
 367     }
 368 
 369     public static boolean printStackTraceWhenAccessFails() {
 370         ensurePrintStackPropertiesSet();
 371         return printStackWhenAccessFails;
 372     }
 373 
 374     public static boolean printStackTraceWhenAccessSucceeds() {
 375         ensurePrintStackPropertiesSet();
 376         return printStackWhenAccessSucceeds;
 377     }
 378 
 379     /**
 380      * Throws IllegalAccessException with the an exception message based on
 381      * the access that is denied.
 382      */
 383     private static void throwIllegalAccessException(Class<?> currentClass,
 384                                                     Class<?> memberClass,
 385                                                     Object target,
 386                                                     int modifiers)
 387         throws IllegalAccessException
 388     {
 389         String currentSuffix = "";
 390         String memberSuffix = "";
 391         Module m1 = currentClass.getModule();
 392         if (m1.isNamed())
 393             currentSuffix = " (in " + m1 + ")";
 394         Module m2 = memberClass.getModule();
 395         if (m2.isNamed())
 396             memberSuffix = " (in " + m2 + ")";
 397 
 398         String memberPackageName = memberClass.getPackageName();
 399 
 400         String msg = currentClass + currentSuffix + " cannot access ";
 401         if (m2.isExported(memberPackageName, m1)) {
 402 
 403             // module access okay so include the modifiers in the message
 404             msg += "a member of " + memberClass + memberSuffix +
 405                     " with modifiers \"" + Modifier.toString(modifiers) + "\"";
 406 
 407         } else {
 408             // module access failed
 409             msg += memberClass + memberSuffix+ " because "
 410                    + m2 + " does not export " + memberPackageName;
 411             if (m2.isNamed()) msg += " to " + m1;
 412         }
 413 
 414         throwIllegalAccessException(msg);
 415     }
 416 
 417     /**
 418      * Throws IllegalAccessException with the given exception message.
 419      */
 420     public static void throwIllegalAccessException(String msg)
 421         throws IllegalAccessException
 422     {
 423         IllegalAccessException e = new IllegalAccessException(msg);
 424         ensurePrintStackPropertiesSet();
 425         if (printStackWhenAccessFails) {
 426             e.printStackTrace(System.err);
 427         }
 428         throw e;
 429     }
 430 }


  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.internal.reflect;
  27 
  28 
  29 import java.lang.reflect.*;
  30 import java.util.HashMap;
  31 import java.util.Map;
  32 import java.util.Objects;
  33 import jdk.internal.HotSpotIntrinsicCandidate;

  34 import jdk.internal.misc.VM;

  35 
  36 /** Common utility routines used by both java.lang and
  37     java.lang.reflect */
  38 
  39 public class Reflection {
  40 
  41     /** Used to filter out fields and methods from certain classes from public
  42         view, where they are sensitive or they may contain VM-internal objects.
  43         These Maps are updated very rarely. Rather than synchronize on
  44         each access, we use copy-on-write */
  45     private static volatile Map<Class<?>,String[]> fieldFilterMap;
  46     private static volatile Map<Class<?>,String[]> methodFilterMap;
  47 
  48     static {
  49         Map<Class<?>,String[]> map = new HashMap<Class<?>,String[]>();
  50         map.put(Reflection.class,
  51             new String[] {"fieldFilterMap", "methodFilterMap"});
  52         map.put(System.class, new String[] {"security"});
  53         map.put(Class.class, new String[] {"classLoader"});
  54         fieldFilterMap = map;


  85 
  86     /**
  87      * Ensures that access to a member is granted and throws
  88      * IllegalAccessException if not.
  89      *
  90      * @param currentClass the class performing the access
  91      * @param memberClass the declaring class of the member being accessed
  92      * @param targetClass the class of target object if accessing instance
  93      *                    field or method;
  94      *                    or the declaring class if accessing constructor;
  95      *                    or null if accessing static field or method
  96      * @param modifiers the member's access modifiers
  97      * @throws IllegalAccessException if access to member is denied
  98      */
  99     public static void ensureMemberAccess(Class<?> currentClass,
 100                                           Class<?> memberClass,
 101                                           Class<?> targetClass,
 102                                           int modifiers)
 103         throws IllegalAccessException
 104     {




 105         if (!verifyMemberAccess(currentClass, memberClass, targetClass, modifiers)) {
 106             throw newIllegalAccessException(currentClass, memberClass, targetClass, modifiers);
 107         }
 108     }
 109 
 110     /**
 111      * Verify access to a member and return {@code true} if it is granted.
 112      *
 113      * @param currentClass the class performing the access
 114      * @param memberClass the declaring class of the member being accessed
 115      * @param targetClass the class of target object if accessing instance
 116      *                    field or method;
 117      *                    or the declaring class if accessing constructor;
 118      *                    or null if accessing static field or method
 119      * @param modifiers the member's access modifiers
 120      * @return {@code true} if access to member is granted
 121      */
 122     public static boolean verifyMemberAccess(Class<?> currentClass,
 123                                              Class<?> memberClass,
 124                                              Class<?> targetClass,
 125                                              int modifiers)
 126     {







 127         if (currentClass == memberClass) {
 128             // Always succeeds
 129             return true;
 130         }
 131 
 132         if (!verifyModuleAccess(currentClass.getModule(), memberClass)) {
 133             return false;
 134         }
 135 
 136         boolean gotIsSameClassPackage = false;
 137         boolean isSameClassPackage = false;
 138 
 139         if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {
 140             isSameClassPackage = isSameClassPackage(currentClass, memberClass);
 141             gotIsSameClassPackage = true;
 142             if (!isSameClassPackage) {
 143                 return false;
 144             }
 145         }
 146 
 147         // At this point we know that currentClass can access memberClass.
 148 
 149         if (Modifier.isPublic(modifiers)) {
 150             return true;
 151         }
 152 
 153         boolean successSoFar = false;
 154 
 155         if (Modifier.isProtected(modifiers)) {
 156             // See if currentClass is a subclass of memberClass
 157             if (isSubclassOf(currentClass, memberClass)) {
 158                 successSoFar = true;


 178         // Additional test for protected instance members
 179         // and protected constructors: JLS 6.6.2
 180         if (targetClass != null && Modifier.isProtected(modifiers) &&
 181             targetClass != currentClass)
 182         {
 183             if (!gotIsSameClassPackage) {
 184                 isSameClassPackage = isSameClassPackage(currentClass, memberClass);
 185                 gotIsSameClassPackage = true;
 186             }
 187             if (!isSameClassPackage) {
 188                 if (!isSubclassOf(targetClass, currentClass)) {
 189                     return false;
 190                 }
 191             }
 192         }
 193 
 194         return true;
 195     }
 196 
 197     /**
 198      * Returns {@code true} if memberClass's module exports memberClass's
 199      * package to currentModule.
 200      */





 201     public static boolean verifyModuleAccess(Module currentModule, Class<?> memberClass) {
 202         Module memberModule = memberClass.getModule();
 203         if (currentModule == memberModule) {
 204             // same module (named or unnamed) or both null if called
 205             // before module system is initialized, which means we are
 206             // dealing with java.base only.
 207             return true;
 208         } else {
 209             String pkg = memberClass.getPackageName();
 210             return memberModule.isExported(pkg, currentModule);






 211         }

 212     }
 213 
 214     /**
 215      * Returns true if two classes in the same package.
 216      */
 217     private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
 218         if (c1.getClassLoader() != c2.getClassLoader())
 219             return false;
 220         return Objects.equals(c1.getPackageName(), c2.getPackageName());
 221     }
 222 
 223     static boolean isSubclassOf(Class<?> queryClass,
 224                                 Class<?> ofClass)
 225     {
 226         while (queryClass != null) {
 227             if (queryClass == ofClass) {
 228                 return true;
 229             }
 230             queryClass = queryClass.getSuperclass();
 231         }


 315      */
 316     public static boolean isCallerSensitive(Method m) {
 317         final ClassLoader loader = m.getDeclaringClass().getClassLoader();
 318         if (VM.isSystemDomainLoader(loader) || isExtClassLoader(loader))  {
 319             return m.isAnnotationPresent(CallerSensitive.class);
 320         }
 321         return false;
 322     }
 323 
 324     private static boolean isExtClassLoader(ClassLoader loader) {
 325         ClassLoader cl = ClassLoader.getSystemClassLoader();
 326         while (cl != null) {
 327             if (cl.getParent() == null && cl == loader) {
 328                 return true;
 329             }
 330             cl = cl.getParent();
 331         }
 332         return false;
 333     }
 334 
































 335     /**
 336      * Returns an IllegalAccessException with an exception message based on
 337      * the access that is denied.
 338      */
 339     public static IllegalAccessException newIllegalAccessException(Class<?> currentClass,
 340                                                                    Class<?> memberClass,
 341                                                                    Class<?> targetClass,
 342                                                                    int modifiers)
 343         throws IllegalAccessException
 344     {
 345         String currentSuffix = "";
 346         String memberSuffix = "";
 347         Module m1 = currentClass.getModule();
 348         if (m1.isNamed())
 349             currentSuffix = " (in " + m1 + ")";
 350         Module m2 = memberClass.getModule();
 351         if (m2.isNamed())
 352             memberSuffix = " (in " + m2 + ")";
 353 
 354         String memberPackageName = memberClass.getPackageName();
 355 
 356         String msg = currentClass + currentSuffix + " cannot access ";
 357         if (m2.isExported(memberPackageName, m1)) {
 358 
 359             // module access okay so include the modifiers in the message
 360             msg += "a member of " + memberClass + memberSuffix +
 361                     " with modifiers \"" + Modifier.toString(modifiers) + "\"";
 362 
 363         } else {
 364             // module access failed
 365             msg += memberClass + memberSuffix+ " because "
 366                    + m2 + " does not export " + memberPackageName;
 367             if (m2.isNamed()) msg += " to " + m1;
 368         }
 369 
 370         return new IllegalAccessException(msg);














 371     }
 372 }
< prev index next >