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