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; 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. 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) + "\""; | 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 (!verifyMemberAccess(currentClass, memberClass, targetClass, modifiers)) { 108 throwIllegalAccessException(currentClass, memberClass, targetClass, modifiers); 109 } 110 } 111 112 /** 113 * Verify access to a member and return {@code true} if it is granted. 114 * 115 * @param currentClass the class performing the access 116 * @param memberClass the declaring class of the member being accessed 117 * @param targetClass the class of target object if accessing instance 118 * field or method; 119 * or the declaring class if accessing constructor; 120 * or null if accessing static field or method 121 * @param modifiers the member's access modifiers 122 * @return {@code true} if access to member is granted 123 */ 124 public static boolean verifyMemberAccess(Class<?> currentClass, 125 Class<?> memberClass, 126 Class<?> targetClass, 127 int modifiers) 128 { 129 Objects.requireNonNull(currentClass); 130 Objects.requireNonNull(memberClass); 131 132 if (currentClass == memberClass) { 133 // Always succeeds 134 return true; 135 } 136 137 if (!verifyModuleAccess(currentClass.getModule(), memberClass)) { 138 return false; 139 } 140 141 boolean gotIsSameClassPackage = false; 142 boolean isSameClassPackage = false; 143 144 if (!Modifier.isPublic(getClassAccessFlags(memberClass))) { 145 isSameClassPackage = isSameClassPackage(currentClass, memberClass); 146 gotIsSameClassPackage = true; 147 if (!isSameClassPackage) { 148 return false; 149 } 150 } 151 152 // At this point we know that currentClass can access memberClass. 153 154 if (Modifier.isPublic(modifiers)) { 155 return true; 156 } 157 158 boolean successSoFar = false; 159 160 if (Modifier.isProtected(modifiers)) { 161 // See if currentClass is a subclass of memberClass 162 if (isSubclassOf(currentClass, memberClass)) { 163 successSoFar = true; 184 // and protected constructors: JLS 6.6.2 185 if (targetClass != null && Modifier.isProtected(modifiers) && 186 targetClass != currentClass) 187 { 188 if (!gotIsSameClassPackage) { 189 isSameClassPackage = isSameClassPackage(currentClass, memberClass); 190 gotIsSameClassPackage = true; 191 } 192 if (!isSameClassPackage) { 193 if (!isSubclassOf(targetClass, currentClass)) { 194 return false; 195 } 196 } 197 } 198 199 return true; 200 } 201 202 /** 203 * Returns {@code true} if memberClass's's module exports memberClass's 204 * package to currentModule. 205 */ 206 public static boolean verifyModuleAccess(Module currentModule, Class<?> memberClass) { 207 Objects.requireNonNull(currentModule); 208 Objects.requireNonNull(memberClass); 209 210 Module memberModule = memberClass.getModule(); 211 212 // module may be null during startup (initLevel 0) 213 if (currentModule == memberModule) 214 return true; // same module (named or unnamed) 215 216 String pkg = memberClass.getPackageName(); 217 boolean allowed = memberModule.isExported(pkg, currentModule); 218 if (allowed && memberModule.isNamed() && printStackTraceWhenAccessSucceeds()) { 219 if (!SharedSecrets.getJavaLangReflectModuleAccess() 220 .isStaticallyExported(memberModule, pkg, currentModule)) { 221 String msg = currentModule + " allowed access to member of " + memberClass; 222 new Exception(msg).printStackTrace(System.err); 223 } 224 } 225 return allowed; 226 } 227 228 /** 229 * Returns true if two classes in the same package. 363 if (s != null) { 364 printStackWhenAccessFails = !s.equalsIgnoreCase("false"); 365 printStackWhenAccessSucceeds = s.equalsIgnoreCase("access"); 366 } 367 printStackPropertiesSet = true; 368 } 369 } 370 371 public static boolean printStackTraceWhenAccessFails() { 372 ensurePrintStackPropertiesSet(); 373 return printStackWhenAccessFails; 374 } 375 376 public static boolean printStackTraceWhenAccessSucceeds() { 377 ensurePrintStackPropertiesSet(); 378 return printStackWhenAccessSucceeds; 379 } 380 381 /** 382 * Throws IllegalAccessException with the an exception message based on 383 * the access that is denied. This method throws meaningful exception only 384 * when {@link #verifyMemberAccess(Class, Class, Class, int)} returns false 385 * for the same parameters. 386 */ 387 public static void throwIllegalAccessException(Class<?> currentClass, 388 Class<?> memberClass, 389 Class<?> targetClass, 390 int modifiers) 391 throws IllegalAccessException 392 { 393 String currentSuffix = ""; 394 String memberSuffix = ""; 395 Module m1 = currentClass.getModule(); 396 if (m1.isNamed()) 397 currentSuffix = " (in " + m1 + ")"; 398 Module m2 = memberClass.getModule(); 399 if (m2.isNamed()) 400 memberSuffix = " (in " + m2 + ")"; 401 402 String memberPackageName = memberClass.getPackageName(); 403 404 String msg = currentClass + currentSuffix + " cannot access "; 405 if (m2.isExported(memberPackageName, m1)) { 406 407 // module access okay so include the modifiers in the message 408 msg += "a member of " + memberClass + memberSuffix + 409 " with modifiers \"" + Modifier.toString(modifiers) + "\""; |