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