1 /*
2 * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
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 java.lang.reflect;
27
28 import java.lang.annotation.Annotation;
29 import java.lang.invoke.MethodHandle;
30 import java.lang.ref.WeakReference;
31
32 import jdk.internal.access.SharedSecrets;
33 import jdk.internal.misc.VM;
34 import jdk.internal.reflect.CallerSensitive;
35 import jdk.internal.reflect.Reflection;
36 import jdk.internal.reflect.ReflectionFactory;
37
38 /**
39 * The {@code AccessibleObject} class is the base class for {@code Field},
40 * {@code Method}, and {@code Constructor} objects (known as <em>reflected
41 * objects</em>). It provides the ability to flag a reflected object as
42 * suppressing checks for Java language access control when it is used. This
43 * permits sophisticated applications with sufficient privilege, such as Java
44 * Object Serialization or other persistence mechanisms, to manipulate objects
45 * in a manner that would normally be prohibited.
46 *
47 * <p> Java language access control prevents use of private members outside
48 * their top-level class; package access members outside their package; protected members
49 * outside their package or subclasses; and public members outside their
50 * module unless they are declared in an {@link Module#isExported(String,Module)
51 * exported} package and the user {@link Module#canRead reads} their module. By
52 * default, Java language access control is enforced (with one variation) when
53 * {@code Field}s, {@code Method}s, or {@code Constructor}s are used to get or
54 * set fields, to invoke methods, or to create and initialize new instances of
55 * classes, respectively. Every reflected object checks that the code using it
56 * is in an appropriate class, package, or module. The check when invoked by
57 * <a href="{@docRoot}/../specs/jni/index.html">JNI code</a> with no Java
58 * class on the stack only succeeds if the member and the declaring class are
59 * public, and the class is in a package that is exported to all modules. </p>
60 *
61 * <p> The one variation from Java language access control is that the checks
62 * by reflected objects assume readability. That is, the module containing
63 * the use of a reflected object is assumed to read the module in which
64 * the underlying field, method, or constructor is declared. </p>
65 *
66 * <p> Whether the checks for Java language access control can be suppressed
67 * (and thus, whether access can be enabled) depends on whether the reflected
68 * object corresponds to a member in an exported or open package
69 * (see {@link #setAccessible(boolean)}). </p>
70 *
71 * @spec jni/index.html Java Native Interface Specification
72 * @jls 6.6 Access Control
73 * @since 1.2
74 */
75 public class AccessibleObject implements AnnotatedElement {
76 static {
77 // AccessibleObject is initialized early in initPhase1
78 SharedSecrets.setJavaLangReflectAccess(new ReflectAccess());
79 }
80
81 /**
82 * Convenience method to set the {@code accessible} flag for an
83 * array of reflected objects.
84 *
85 * <p> This method may be used to enable access to all reflected objects in
86 * the array when access to each reflected object can be enabled as
87 * specified by {@link #setAccessible(boolean) setAccessible(boolean)}. </p>
88 *
89 * <p>A {@code SecurityException} is thrown if any of the elements of
90 * the input {@code array} is a {@link java.lang.reflect.Constructor}
91 * object for the class {@code java.lang.Class} and {@code flag} is true.
92 *
93 * @param array the array of AccessibleObjects
94 * @param flag the new value for the {@code accessible} flag
95 * in each object
96 * @throws InaccessibleObjectException if access cannot be enabled for all
97 * objects in the array
98 * @throws SecurityException if an element in the array is a constructor for {@code
99 * java.lang.Class}
100 */
101 @CallerSensitive
102 public static void setAccessible(AccessibleObject[] array, boolean flag) {
103 if (flag) {
104 Class<?> caller = Reflection.getCallerClass();
105 array = array.clone();
106 for (AccessibleObject ao : array) {
107 ao.checkCanSetAccessible(caller);
108 }
109 }
110 for (AccessibleObject ao : array) {
111 ao.setAccessible0(flag);
112 }
113 }
114
115 /**
116 * Set the {@code accessible} flag for this reflected object to
117 * the indicated boolean value. A value of {@code true} indicates that
118 * the reflected object should suppress checks for Java language access
119 * control when it is used. A value of {@code false} indicates that
120 * the reflected object should enforce checks for Java language access
121 * control when it is used, with the variation noted in the class description.
122 *
123 * <p> This method may be used by a caller in class {@code C} to enable
124 * access to a {@link Member member} of {@link Member#getDeclaringClass()
125 * declaring class} {@code D} if any of the following hold: </p>
126 *
127 * <ul>
128 * <li> {@code C} and {@code D} are in the same module. </li>
129 *
130 * <li> The member is {@code public} and {@code D} is {@code public} in
131 * a package that the module containing {@code D} {@link
132 * Module#isExported(String,Module) exports} to at least the module
133 * containing {@code C}. </li>
134 *
135 * <li> The member is {@code protected} {@code static}, {@code D} is
136 * {@code public} in a package that the module containing {@code D}
137 * exports to at least the module containing {@code C}, and {@code C}
138 * is a subclass of {@code D}. </li>
139 *
140 * <li> {@code D} is in a package that the module containing {@code D}
141 * {@link Module#isOpen(String,Module) opens} to at least the module
142 * containing {@code C}.
143 * All packages in unnamed and open modules are open to all modules and
144 * so this method always succeeds when {@code D} is in an unnamed or
145 * open module. </li>
146 * </ul>
147 *
148 * <p> This method may be used by <a href="{@docRoot}/../specs/jni/index.html">JNI code</a>
149 * with no caller class on the stack to enable access to a {@link Member member}
150 * of {@link Member#getDeclaringClass() declaring class} {@code D} if and only if:
151 * <ul>
152 * <li> The member is {@code public} and {@code D} is {@code public} in
153 * a package that the module containing {@code D} {@link
154 * Module#isExported(String,Module) exports} unconditionally. </li>
155 * </ul>
156 *
157 * <p> This method cannot be used to enable access to private members,
158 * members with default (package) access, protected instance members, or
159 * protected constructors when the declaring class is in a different module
160 * to the caller and the package containing the declaring class is not open
161 * to the caller's module. </p>
162 *
163 * <p> This method cannot be used to enable {@linkplain Field#set <em>write</em>}
164 * access to a <em>non-modifiable</em> final field. The following fields
165 * are non-modifiable:
166 * <ul>
167 * <li>static final fields declared in any class or interface</li>
168 * <li>final fields declared in a {@linkplain Class#isHidden() hidden class}</li>
169 * <li>final fields declared in a {@linkplain Class#isRecord() record}</li>
170 * </ul>
171 * <p> The {@code accessible} flag when {@code true} suppresses Java language access
172 * control checks to only enable {@linkplain Field#get <em>read</em>} access to
173 * these non-modifiable final fields.
174 *
175 * @param flag the new value for the {@code accessible} flag
176 * @throws InaccessibleObjectException if access cannot be enabled
177 *
178 * @spec jni/index.html Java Native Interface Specification
179 * @see #trySetAccessible
180 * @see java.lang.invoke.MethodHandles#privateLookupIn
181 */
182 @CallerSensitive // overrides in Method/Field/Constructor are @CS
183 public void setAccessible(boolean flag) {
184 setAccessible0(flag);
185 }
186
187 /**
188 * Sets the accessible flag and returns the new value
189 */
190 boolean setAccessible0(boolean flag) {
191 this.override = flag;
192 return flag;
193 }
194
195 /**
196 * Set the {@code accessible} flag for this reflected object to {@code true}
197 * if possible. This method sets the {@code accessible} flag, as if by
198 * invoking {@link #setAccessible(boolean) setAccessible(true)}, and returns
199 * the possibly-updated value for the {@code accessible} flag. If access
200 * cannot be enabled, i.e. the checks or Java language access control cannot
201 * be suppressed, this method returns {@code false} (as opposed to {@code
202 * setAccessible(true)} throwing {@code InaccessibleObjectException} when
203 * it fails).
204 *
205 * <p> This method is a no-op if the {@code accessible} flag for
206 * this reflected object is {@code true}.
207 *
208 * <p> For example, a caller can invoke {@code trySetAccessible}
209 * on a {@code Method} object for a private instance method
210 * {@code p.T::privateMethod} to suppress the checks for Java language access
211 * control when the {@code Method} is invoked.
212 * If {@code p.T} class is in a different module to the caller and
213 * package {@code p} is open to at least the caller's module,
214 * the code below successfully sets the {@code accessible} flag
215 * to {@code true}.
216 *
217 * <pre>
218 * {@code
219 * p.T obj = ....; // instance of p.T
220 * :
221 * Method m = p.T.class.getDeclaredMethod("privateMethod");
222 * if (m.trySetAccessible()) {
223 * m.invoke(obj);
224 * } else {
225 * // package p is not opened to the caller to access private member of T
226 * ...
227 * }
228 * }</pre>
229 *
230 * <p> If this method is invoked by <a href="{@docRoot}/../specs/jni/index.html">JNI code</a>
231 * with no caller class on the stack, the {@code accessible} flag can
232 * only be set if the member and the declaring class are public, and
233 * the class is in a package that is exported unconditionally. </p>
234 *
235 * @return {@code true} if the {@code accessible} flag is set to {@code true};
236 * {@code false} if access cannot be enabled.
237 *
238 * @spec jni/index.html Java Native Interface Specification
239 * @since 9
240 * @see java.lang.invoke.MethodHandles#privateLookupIn
241 */
242 @CallerSensitive
243 public final boolean trySetAccessible() {
244 if (override == true) return true;
245
246 // if it's not a Constructor, Method, Field then no access check
247 if (!Member.class.isInstance(this)) {
248 return setAccessible0(true);
249 }
250
251 // does not allow to suppress access check for Class's constructor
252 Class<?> declaringClass = ((Member) this).getDeclaringClass();
253 if (declaringClass == Class.class && this instanceof Constructor) {
254 return false;
255 }
256
257 if (checkCanSetAccessible(Reflection.getCallerClass(),
258 declaringClass,
259 false)) {
260 return setAccessible0(true);
261 } else {
262 return false;
263 }
264 }
265
266
267 /**
268 * If the given AccessibleObject is a {@code Constructor}, {@code Method}
269 * or {@code Field} then checks that its declaring class is in a package
270 * that can be accessed by the given caller of setAccessible.
271 */
272 void checkCanSetAccessible(Class<?> caller) {
273 // do nothing, needs to be overridden by Constructor, Method, Field
274 }
275
276 final void checkCanSetAccessible(Class<?> caller, Class<?> declaringClass) {
277 checkCanSetAccessible(caller, declaringClass, true);
278 }
279
280 private boolean checkCanSetAccessible(Class<?> caller,
281 Class<?> declaringClass,
282 boolean throwExceptionIfDenied) {
283 if (caller == MethodHandle.class) {
284 throw new IllegalCallerException(); // should not happen
285 }
286
287 if (caller == null) {
288 // No caller frame when a native thread attaches to the VM
289 // only allow access to a public accessible member
290 boolean canAccess = Reflection.verifyPublicMemberAccess(declaringClass, declaringClass.getModifiers());
291 if (!canAccess && throwExceptionIfDenied) {
292 throwInaccessibleObjectException(caller, declaringClass);
293 }
294 return canAccess;
295 }
296
297 Module callerModule = caller.getModule();
298 Module declaringModule = declaringClass.getModule();
299
300 if (callerModule == declaringModule) return true;
301 if (callerModule == Object.class.getModule()) return true;
302 if (!declaringModule.isNamed()) return true;
303
304 String pn = declaringClass.getPackageName();
305 int modifiers = ((Member)this).getModifiers();
306
307 // class is public and package is exported to caller
308 boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers());
309 if (isClassPublic && declaringModule.isExported(pn, callerModule)) {
310 // member is public
311 if (Modifier.isPublic(modifiers)) {
312 return true;
313 }
314
315 // member is protected-static
316 if (Modifier.isProtected(modifiers)
317 && Modifier.isStatic(modifiers)
318 && isSubclassOf(caller, declaringClass)) {
319 return true;
320 }
321 }
322
323 // package is open to caller
324 if (declaringModule.isOpen(pn, callerModule)) {
325 return true;
326 }
327
328 if (throwExceptionIfDenied) {
329 throwInaccessibleObjectException(caller, declaringClass);
330 }
331 return false;
332 }
333
334 private void throwInaccessibleObjectException(Class<?> caller, Class<?> declaringClass) {
335 boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers());
336 String pn = declaringClass.getPackageName();
337 int modifiers = ((Member)this).getModifiers();
338
339 // not accessible
340 String msg = "Unable to make ";
341 if (this instanceof Field)
342 msg += "field ";
343 msg += this + " accessible";
344 msg += caller == null ? " by JNI attached native thread with no caller frame: " : ": ";
345 msg += declaringClass.getModule() + " does not \"";
346 if (isClassPublic && Modifier.isPublic(modifiers))
347 msg += "exports";
348 else
349 msg += "opens";
350 msg += " " + pn + "\"" ;
351 if (caller != null)
352 msg += " to " + caller.getModule();
353 InaccessibleObjectException e = new InaccessibleObjectException(msg);
354 if (printStackTraceWhenAccessFails()) {
355 e.printStackTrace(System.err);
356 }
357 throw e;
358 }
359
360 private boolean isSubclassOf(Class<?> queryClass, Class<?> ofClass) {
361 while (queryClass != null) {
362 if (queryClass == ofClass) {
363 return true;
364 }
365 queryClass = queryClass.getSuperclass();
366 }
367 return false;
368 }
369
370 /**
371 * Returns a short descriptive string to describe this object in log messages.
372 */
373 String toShortString() {
374 return toString();
375 }
376
377 /**
378 * Get the value of the {@code accessible} flag for this reflected object.
379 *
380 * @return the value of the object's {@code accessible} flag
381 *
382 * @deprecated
383 * This method is deprecated because its name hints that it checks
384 * if the reflected object is accessible when it actually indicates
385 * if the checks for Java language access control are suppressed.
386 * This method may return {@code false} on a reflected object that is
387 * accessible to the caller. To test if this reflected object is accessible,
388 * it should use {@link #canAccess(Object)}.
389 */
390 @Deprecated(since="9")
391 public boolean isAccessible() {
392 return override;
393 }
394
395 /**
396 * Test if the caller can access this reflected object. If this reflected
397 * object corresponds to an instance method or field then this method tests
398 * if the caller can access the given {@code obj} with the reflected object.
399 * For instance methods or fields then the {@code obj} argument must be an
400 * instance of the {@link Member#getDeclaringClass() declaring class}. For
401 * static members and constructors then {@code obj} must be {@code null}.
402 *
403 * <p> This method returns {@code true} if the {@code accessible} flag
404 * is set to {@code true}, i.e. the checks for Java language access control
405 * are suppressed, or if the caller can access the member as
406 * specified in <cite>The Java Language Specification</cite>,
407 * with the variation noted in the class description.
408 * If this method is invoked by <a href="{@docRoot}/../specs/jni/index.html">JNI code</a>
409 * with no caller class on the stack, this method returns {@code true}
410 * if the member and the declaring class are public, and the class is in
411 * a package that is exported unconditionally. </p>
412 *
413 * @param obj an instance object of the declaring class of this reflected
414 * object if it is an instance method or field
415 *
416 * @return {@code true} if the caller can access this reflected object.
417 *
418 * @throws IllegalArgumentException
419 * <ul>
420 * <li> if this reflected object is a static member or constructor and
421 * the given {@code obj} is non-{@code null}, or </li>
422 * <li> if this reflected object is an instance method or field
423 * and the given {@code obj} is {@code null} or of type
424 * that is not a subclass of the {@link Member#getDeclaringClass()
425 * declaring class} of the member.</li>
426 * </ul>
427 *
428 * @spec jni/index.html Java Native Interface Specification
429 * @since 9
430 * @jls 6.6 Access Control
431 * @see #trySetAccessible
432 * @see #setAccessible(boolean)
433 */
434 @CallerSensitive
435 public final boolean canAccess(Object obj) {
436 if (!Member.class.isInstance(this)) {
437 return override;
438 }
439
440 Class<?> declaringClass = ((Member) this).getDeclaringClass();
441 int modifiers = ((Member) this).getModifiers();
442 if (!Modifier.isStatic(modifiers) &&
443 (this instanceof Method || this instanceof Field)) {
444 if (obj == null) {
445 throw new IllegalArgumentException("null object for " + this);
446 }
447 // if this object is an instance member, the given object
448 // must be a subclass of the declaring class of this reflected object
449 if (!declaringClass.isInstance(obj)) {
450 throw new IllegalArgumentException("object is not an instance of "
451 + declaringClass.getName());
452 }
453 } else if (obj != null) {
454 throw new IllegalArgumentException("non-null object for " + this);
455 }
456
457 // access check is suppressed
458 if (override) return true;
459
460 Class<?> caller = Reflection.getCallerClass();
461 Class<?> targetClass;
462 if (this instanceof Constructor) {
463 targetClass = declaringClass;
464 } else {
465 targetClass = Modifier.isStatic(modifiers) ? null : obj.getClass();
466 }
467 return verifyAccess(caller, declaringClass, targetClass, modifiers);
468 }
469
470 /**
471 * Constructor: only used by the Java Virtual Machine.
472 */
473 @Deprecated(since="17")
474 protected AccessibleObject() {}
475
476 // Indicates whether language-level access checks are overridden
477 // by this object. Initializes to "false". This field is used by
478 // Field, Method, and Constructor.
479 //
480 // NOTE: for security purposes, this field must not be visible
481 // outside this package.
482 boolean override;
483
484 // Reflection factory used by subclasses for creating field,
485 // method, and constructor accessors. Note that this is called
486 // very early in the bootstrapping process.
487 static final ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
488
489 /**
490 * {@inheritDoc}
491 *
492 * <p> Note that any annotation returned by this method is a
493 * declaration annotation.
494 *
495 * @implSpec
496 * The default implementation throws {@link
497 * UnsupportedOperationException}; subclasses should override this method.
498 *
499 * @throws NullPointerException {@inheritDoc}
500 * @since 1.5
501 */
502 @Override
503 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
504 throw new UnsupportedOperationException("All subclasses should override this method");
505 }
506
507 /**
508 * {@inheritDoc}
509 *
510 * @throws NullPointerException {@inheritDoc}
511 * @since 1.5
512 */
513 @Override
514 public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
515 return AnnotatedElement.super.isAnnotationPresent(annotationClass);
516 }
517
518 /**
519 * {@inheritDoc}
520 *
521 * <p> Note that any annotations returned by this method are
522 * declaration annotations.
523 *
524 * @implSpec
525 * The default implementation throws {@link
526 * UnsupportedOperationException}; subclasses should override this method.
527 *
528 * @throws NullPointerException {@inheritDoc}
529 * @since 1.8
530 */
531 @Override
532 public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
533 throw new UnsupportedOperationException("All subclasses should override this method");
534 }
535
536 /**
537 * {@inheritDoc}
538 *
539 * <p> Note that any annotations returned by this method are
540 * declaration annotations.
541 *
542 * @since 1.5
543 */
544 @Override
545 public Annotation[] getAnnotations() {
546 return getDeclaredAnnotations();
547 }
548
549 /**
550 * {@inheritDoc}
551 *
552 * <p> Note that any annotation returned by this method is a
553 * declaration annotation.
554 *
555 * @throws NullPointerException {@inheritDoc}
556 * @since 1.8
557 */
558 @Override
559 public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
560 // Only annotations on classes are inherited, for all other
561 // objects getDeclaredAnnotation is the same as
562 // getAnnotation.
563 return getAnnotation(annotationClass);
564 }
565
566 /**
567 * {@inheritDoc}
568 *
569 * <p> Note that any annotations returned by this method are
570 * declaration annotations.
571 *
572 * @throws NullPointerException {@inheritDoc}
573 * @since 1.8
574 */
575 @Override
576 public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
577 // Only annotations on classes are inherited, for all other
578 // objects getDeclaredAnnotationsByType is the same as
579 // getAnnotationsByType.
580 return getAnnotationsByType(annotationClass);
581 }
582
583 /**
584 * {@inheritDoc}
585 *
586 * <p> Note that any annotations returned by this method are
587 * declaration annotations.
588 *
589 * @implSpec
590 * The default implementation throws {@link
591 * UnsupportedOperationException}; subclasses should override this method.
592 *
593 * @since 1.5
594 */
595 @Override
596 public Annotation[] getDeclaredAnnotations() {
597 throw new UnsupportedOperationException("All subclasses should override this method");
598 }
599
600 // Shared access checking logic.
601
602 // For non-public members or members in package-private classes,
603 // it is necessary to perform somewhat expensive access checks.
604 // If the access check succeeds for a given class, it will
605 // always succeed; we speed up the check in the common case by
606 // remembering the last Class for which the check succeeded.
607 //
608 // The simple access check for Constructor is to see if
609 // the caller has already been seen, verified, and cached.
610 //
611 // A more complicated access check cache is needed for Method and Field
612 // The cache can be either null (empty cache), {caller,targetClass} pair,
613 // or a caller (with targetClass implicitly equal to memberClass).
614 // In the {caller,targetClass} case, the targetClass is always different
615 // from the memberClass.
616 volatile Object accessCheckCache;
617
618 private static class Cache {
619 final WeakReference<Class<?>> callerRef;
620 final WeakReference<Class<?>> targetRef;
621
622 Cache(Class<?> caller, Class<?> target) {
623 this.callerRef = new WeakReference<>(caller);
624 this.targetRef = new WeakReference<>(target);
625 }
626
627 boolean isCacheFor(Class<?> caller, Class<?> refc) {
628 return callerRef.refersTo(caller) && targetRef.refersTo(refc);
629 }
630
631 static Object protectedMemberCallerCache(Class<?> caller, Class<?> refc) {
632 return new Cache(caller, refc);
633 }
634 }
635
636 /*
637 * Returns true if the previous access check was verified for the
638 * given caller accessing a protected member with an instance of
639 * the given targetClass where the target class is different than
640 * the declaring member class.
641 */
642 private boolean isAccessChecked(Class<?> caller, Class<?> targetClass) {
643 Object cache = accessCheckCache; // read volatile
644 if (cache instanceof Cache c) {
645 return c.isCacheFor(caller, targetClass);
646 }
647 return false;
648 }
649
650 /*
651 * Returns true if the previous access check was verified for the
652 * given caller accessing a static member or an instance member of
653 * the target class that is the same as the declaring member class.
654 */
655 private boolean isAccessChecked(Class<?> caller) {
656 Object cache = accessCheckCache; // read volatile
657 if (cache instanceof WeakReference) {
658 @SuppressWarnings("unchecked")
659 WeakReference<Class<?>> ref = (WeakReference<Class<?>>) cache;
660 return ref.refersTo(caller);
661 }
662 return false;
663 }
664
665 final void checkAccess(Class<?> caller, Class<?> memberClass,
666 Class<?> targetClass, int modifiers)
667 throws IllegalAccessException
668 {
669 if (!verifyAccess(caller, memberClass, targetClass, modifiers)) {
670 IllegalAccessException e = Reflection.newIllegalAccessException(
671 caller, memberClass, targetClass, modifiers);
672 if (printStackTraceWhenAccessFails()) {
673 e.printStackTrace(System.err);
674 }
675 throw e;
676 }
677 }
678
679 final boolean verifyAccess(Class<?> caller, Class<?> memberClass,
680 Class<?> targetClass, int modifiers)
681 {
682 if (caller == memberClass) { // quick check
683 return true; // ACCESS IS OK
684 }
685 if (targetClass != null // instance member or constructor
686 && Modifier.isProtected(modifiers)
687 && targetClass != memberClass) {
688 if (isAccessChecked(caller, targetClass)) {
689 return true; // ACCESS IS OK
690 }
691 } else if (isAccessChecked(caller)) {
692 // Non-protected case (or targetClass == memberClass or static member).
693 return true; // ACCESS IS OK
694 }
695
696 // If no return, fall through to the slow path.
697 return slowVerifyAccess(caller, memberClass, targetClass, modifiers);
698 }
699
700 // Keep all this slow stuff out of line:
701 private boolean slowVerifyAccess(Class<?> caller, Class<?> memberClass,
702 Class<?> targetClass, int modifiers)
703 {
704
705 if (caller == null) {
706 // No caller frame when a native thread attaches to the VM
707 // only allow access to a public accessible member
708 return Reflection.verifyPublicMemberAccess(memberClass, modifiers);
709 }
710
711 if (!Reflection.verifyMemberAccess(caller, memberClass, targetClass, modifiers)) {
712 // access denied
713 return false;
714 }
715
716 // Success: Update the cache.
717 Object cache = (targetClass != null
718 && Modifier.isProtected(modifiers)
719 && targetClass != memberClass)
720 ? Cache.protectedMemberCallerCache(caller, targetClass)
721 : new WeakReference<>(caller);
722 accessCheckCache = cache; // write volatile
723 return true;
724 }
725
726 // true to print a stack trace when access fails
727 private static volatile boolean printStackWhenAccessFails;
728
729 // true if printStack* values are initialized
730 private static volatile boolean printStackPropertiesSet;
731
732 /**
733 * Returns true if a stack trace should be printed when access fails.
734 */
735 private static boolean printStackTraceWhenAccessFails() {
736 if (!printStackPropertiesSet && VM.initLevel() >= 1) {
737 String s = System.getProperty("sun.reflect.debugModuleAccessChecks");
738 if (s != null) {
739 printStackWhenAccessFails = !s.equalsIgnoreCase("false");
740 }
741 printStackPropertiesSet = true;
742 }
743 return printStackWhenAccessFails;
744 }
745
746 /**
747 * Returns the root AccessibleObject; or null if this object is the root.
748 *
749 * All subclasses override this method.
750 */
751 AccessibleObject getRoot() {
752 throw new InternalError();
753 }
754 }