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