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