1 /*
  2  * Copyright (c) 1997, 2021, 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  * @jls 6.6 Access Control
 75  * @since 1.2
 76  * @revised 9
 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      * @revised 9
122      */
123     @CallerSensitive
124     public static void setAccessible(AccessibleObject[] array, boolean flag) {
125         checkPermission();
126         if (flag) {
127             Class<?> caller = Reflection.getCallerClass();
128             array = array.clone();
129             for (AccessibleObject ao : array) {
130                 ao.checkCanSetAccessible(caller);
131             }
132         }
133         for (AccessibleObject ao : array) {
134             ao.setAccessible0(flag);
135         }
136     }
137 
138     /**
139      * Set the {@code accessible} flag for this reflected object to
140      * the indicated boolean value.  A value of {@code true} indicates that
141      * the reflected object should suppress checks for Java language access
142      * control when it is used. A value of {@code false} indicates that
143      * the reflected object should enforce checks for Java language access
144      * control when it is used, with the variation noted in the class description.
145      *
146      * <p> This method may be used by a caller in class {@code C} to enable
147      * access to a {@link Member member} of {@link Member#getDeclaringClass()
148      * declaring class} {@code D} if any of the following hold: </p>
149      *
150      * <ul>
151      *     <li> {@code C} and {@code D} are in the same module. </li>
152      *
153      *     <li> The member is {@code public} and {@code D} is {@code public} in
154      *     a package that the module containing {@code D} {@link
155      *     Module#isExported(String,Module) exports} to at least the module
156      *     containing {@code C}. </li>
157      *
158      *     <li> The member is {@code protected} {@code static}, {@code D} is
159      *     {@code public} in a package that the module containing {@code D}
160      *     exports to at least the module containing {@code C}, and {@code C}
161      *     is a subclass of {@code D}. </li>
162      *
163      *     <li> {@code D} is in a package that the module containing {@code D}
164      *     {@link Module#isOpen(String,Module) opens} to at least the module
165      *     containing {@code C}.
166      *     All packages in unnamed and open modules are open to all modules and
167      *     so this method always succeeds when {@code D} is in an unnamed or
168      *     open module. </li>
169      * </ul>
170      *
171      * <p> This method cannot be used to enable access to private members,
172      * members with default (package) access, protected instance members, or
173      * protected constructors when the declaring class is in a different module
174      * to the caller and the package containing the declaring class is not open
175      * to the caller's module. </p>
176      *
177      * <p> This method cannot be used to enable {@linkplain Field#set <em>write</em>}
178      * access to a <em>non-modifiable</em> final field.  The following fields
179      * are non-modifiable:
180      * <ul>
181      * <li>static final fields declared in any class or interface</li>
182      * <li>final fields declared in a {@linkplain Class#isHidden() hidden class}</li>

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