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