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


 201     public static boolean verifyModuleAccess(Class<?> currentClass,
 202                                              Class<?> memberClass) {
 203         return verifyModuleAccess(currentClass.getModule(), memberClass);
 204     }
 205 
 206     public static boolean verifyModuleAccess(Module currentModule, Class<?> memberClass) {
 207         Module memberModule = memberClass.getModule();
 208 
 209         // module may be null during startup (initLevel 0)
 210         if (currentModule == memberModule)
 211            return true;  // same module (named or unnamed)
 212 
 213         // memberClass may be primitive or array class
 214         Class<?> c = memberClass;
 215         while (c.isArray()) {
 216             c = c.getComponentType();
 217         }
 218         if (c.isPrimitive())
 219             return true;
 220 
 221         // check that memberModule exports the package to currentModule
 222         return memberModule.isExported(c.getPackageName(), currentModule);








 223     }
 224 
 225     /**
 226      * Returns true if two classes in the same package.
 227      */
 228     private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
 229         if (c1.getClassLoader() != c2.getClassLoader())
 230             return false;
 231         while (c1.isArray())
 232             c1 = c1.getComponentType();
 233         while (c2.isArray())
 234             c2 = c2.getComponentType();
 235         return Objects.equals(c1.getPackageName(), c2.getPackageName());
 236     }
 237 
 238     static boolean isSubclassOf(Class<?> queryClass,
 239                                 Class<?> ofClass)
 240     {
 241         while (queryClass != null) {
 242             if (queryClass == ofClass) {


 331     public static boolean isCallerSensitive(Method m) {
 332         final ClassLoader loader = m.getDeclaringClass().getClassLoader();
 333         if (VM.isSystemDomainLoader(loader) || isExtClassLoader(loader))  {
 334             return m.isAnnotationPresent(CallerSensitive.class);
 335         }
 336         return false;
 337     }
 338 
 339     private static boolean isExtClassLoader(ClassLoader loader) {
 340         ClassLoader cl = ClassLoader.getSystemClassLoader();
 341         while (cl != null) {
 342             if (cl.getParent() == null && cl == loader) {
 343                 return true;
 344             }
 345             cl = cl.getParent();
 346         }
 347         return false;
 348     }
 349 
 350 
 351     // true to print a stack trace when IAE is thrown
 352     private static volatile boolean printStackWhenAccessFails;
 353 
 354     // true if printStackWhenAccessFails has been initialized
 355     private static volatile boolean printStackWhenAccessFailsSet;
 356 
 357     private static void printStackTraceIfNeeded(Throwable e) {
 358         if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) {



 359             String s = GetPropertyAction.privilegedGetProperty(
 360                     "sun.reflect.debugModuleAccessChecks");
 361             printStackWhenAccessFails =
 362                     (s != null && !s.equalsIgnoreCase("false"));
 363             printStackWhenAccessFailsSet = true;
 364         }
 365         if (printStackWhenAccessFails) {
 366             e.printStackTrace();











 367         }




 368     }
 369 
 370     /**
 371      * Throws IllegalAccessException with the an exception message based on
 372      * the access that is denied.
 373      */
 374     private static void throwIllegalAccessException(Class<?> currentClass,
 375                                                     Class<?> memberClass,
 376                                                     Object target,
 377                                                     int modifiers)
 378         throws IllegalAccessException
 379     {
 380         String currentSuffix = "";
 381         String memberSuffix = "";
 382         Module m1 = currentClass.getModule();
 383         if (m1.isNamed())
 384             currentSuffix = " (in " + m1 + ")";
 385         Module m2 = memberClass.getModule();
 386         if (m2.isNamed())
 387             memberSuffix = " (in " + m2 + ")";


 399             msg += "a member of " + memberClass + memberSuffix +
 400                     " with modifiers \"" + Modifier.toString(modifiers) + "\"";
 401 
 402         } else {
 403             // module access failed
 404             msg += memberClass + memberSuffix+ " because "
 405                    + m2 + " does not export " + memberPackageName;
 406             if (m2.isNamed()) msg += " to " + m1;
 407         }
 408 
 409         throwIllegalAccessException(msg);
 410     }
 411 
 412     /**
 413      * Throws IllegalAccessException with the given exception message.
 414      */
 415     public static void throwIllegalAccessException(String msg)
 416         throws IllegalAccessException
 417     {
 418         IllegalAccessException e = new IllegalAccessException(msg);
 419         printStackTraceIfNeeded(e);
 420         throw e;

 421     }
 422 
 423     /**
 424      * Throws InaccessibleObjectException with the given exception message.
 425      */
 426     public static void throwInaccessibleObjectException(String msg) {
 427         InaccessibleObjectException e = new InaccessibleObjectException(msg);
 428         printStackTraceIfNeeded(e);
 429         throw e;
 430     }
 431 
 432 }


  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"});


 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         // memberClass may be primitive or array class
 215         Class<?> c = memberClass;
 216         while (c.isArray()) {
 217             c = c.getComponentType();
 218         }
 219         if (c.isPrimitive())
 220             return true;
 221 
 222         String pkg = c.getPackageName();
 223         boolean allowed = memberModule.isExported(pkg, currentModule);
 224         if (allowed && memberModule.isNamed() && printStackTraceWhenAccessSucceeds()) {
 225             if (!SharedSecrets.getJavaLangReflectModuleAccess()
 226                     .isStaticallyExported(memberModule, pkg, currentModule)) {
 227                 String msg = currentModule + " allowed access to member of " + memberClass;
 228                 new Exception(msg).printStackTrace(System.err);
 229             }
 230         }
 231         return allowed;
 232     }
 233 
 234     /**
 235      * Returns true if two classes in the same package.
 236      */
 237     private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
 238         if (c1.getClassLoader() != c2.getClassLoader())
 239             return false;
 240         while (c1.isArray())
 241             c1 = c1.getComponentType();
 242         while (c2.isArray())
 243             c2 = c2.getComponentType();
 244         return Objects.equals(c1.getPackageName(), c2.getPackageName());
 245     }
 246 
 247     static boolean isSubclassOf(Class<?> queryClass,
 248                                 Class<?> ofClass)
 249     {
 250         while (queryClass != null) {
 251             if (queryClass == ofClass) {


 340     public static boolean isCallerSensitive(Method m) {
 341         final ClassLoader loader = m.getDeclaringClass().getClassLoader();
 342         if (VM.isSystemDomainLoader(loader) || isExtClassLoader(loader))  {
 343             return m.isAnnotationPresent(CallerSensitive.class);
 344         }
 345         return false;
 346     }
 347 
 348     private static boolean isExtClassLoader(ClassLoader loader) {
 349         ClassLoader cl = ClassLoader.getSystemClassLoader();
 350         while (cl != null) {
 351             if (cl.getParent() == null && cl == loader) {
 352                 return true;
 353             }
 354             cl = cl.getParent();
 355         }
 356         return false;
 357     }
 358 
 359 
 360     // true to print a stack trace when access fails
 361     private static volatile boolean printStackWhenAccessFails;
 362 
 363     // true to print a stack trace when access succeeds
 364     private static volatile boolean printStackWhenAccessSucceeds;
 365 
 366     // true if printStack* values are initialized
 367     private static volatile boolean printStackPropertiesSet;
 368 
 369     private static void ensurePrintStackPropertiesSet() {
 370         if (!printStackPropertiesSet && VM.initLevel() >= 1) {
 371             String s = GetPropertyAction.privilegedGetProperty(
 372                     "sun.reflect.debugModuleAccessChecks");
 373             if (s != null) {
 374                 printStackWhenAccessFails = !s.equalsIgnoreCase("false");
 375                 printStackWhenAccessSucceeds = s.equalsIgnoreCase("access");
 376             }
 377             printStackPropertiesSet = true;
 378         }
 379     }
 380 
 381     public static void enableStackTraces() {
 382         printStackWhenAccessFails = true;
 383         printStackWhenAccessSucceeds = true;
 384         printStackPropertiesSet = true;
 385     }
 386 
 387     public static boolean printStackTraceWhenAccessFails() {
 388         ensurePrintStackPropertiesSet();
 389         return printStackWhenAccessFails;
 390     }
 391 
 392     public static boolean printStackTraceWhenAccessSucceeds() {
 393         ensurePrintStackPropertiesSet();
 394         return printStackWhenAccessSucceeds;
 395     }
 396 
 397     /**
 398      * Throws IllegalAccessException with the an exception message based on
 399      * the access that is denied.
 400      */
 401     private static void throwIllegalAccessException(Class<?> currentClass,
 402                                                     Class<?> memberClass,
 403                                                     Object target,
 404                                                     int modifiers)
 405         throws IllegalAccessException
 406     {
 407         String currentSuffix = "";
 408         String memberSuffix = "";
 409         Module m1 = currentClass.getModule();
 410         if (m1.isNamed())
 411             currentSuffix = " (in " + m1 + ")";
 412         Module m2 = memberClass.getModule();
 413         if (m2.isNamed())
 414             memberSuffix = " (in " + m2 + ")";


 426             msg += "a member of " + memberClass + memberSuffix +
 427                     " with modifiers \"" + Modifier.toString(modifiers) + "\"";
 428 
 429         } else {
 430             // module access failed
 431             msg += memberClass + memberSuffix+ " because "
 432                    + m2 + " does not export " + memberPackageName;
 433             if (m2.isNamed()) msg += " to " + m1;
 434         }
 435 
 436         throwIllegalAccessException(msg);
 437     }
 438 
 439     /**
 440      * Throws IllegalAccessException with the given exception message.
 441      */
 442     public static void throwIllegalAccessException(String msg)
 443         throws IllegalAccessException
 444     {
 445         IllegalAccessException e = new IllegalAccessException(msg);
 446         ensurePrintStackPropertiesSet();
 447         if (printStackWhenAccessFails) {
 448             e.printStackTrace(System.err);
 449         }







 450         throw e;
 451     }

 452 }
< prev index next >