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 }