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