1 /*
   2  * Copyright (c) 2001, 2017, 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 jdk.internal.reflect;
  27 
  28 import java.io.Externalizable;
  29 import java.io.ObjectInputStream;
  30 import java.io.ObjectOutputStream;
  31 import java.io.ObjectStreamClass;
  32 import java.io.OptionalDataException;
  33 import java.io.Serializable;
  34 import java.lang.invoke.MethodHandle;
  35 import java.lang.invoke.MethodHandles;
  36 import java.lang.reflect.Field;
  37 import java.lang.reflect.Executable;
  38 import java.lang.reflect.InvocationTargetException;
  39 import java.lang.reflect.Method;
  40 import java.lang.reflect.Constructor;
  41 import java.lang.reflect.Modifier;
  42 import java.security.Permission;
  43 import java.security.PrivilegedAction;
  44 import java.util.Objects;
  45 import java.util.Properties;
  46 
  47 import jdk.internal.misc.VM;
  48 import sun.reflect.misc.ReflectUtil;
  49 import sun.security.action.GetPropertyAction;
  50 
  51 /** <P> The master factory for all reflective objects, both those in
  52     java.lang.reflect (Fields, Methods, Constructors) as well as their
  53     delegates (FieldAccessors, MethodAccessors, ConstructorAccessors).
  54     </P>
  55 
  56     <P> The methods in this class are extremely unsafe and can cause
  57     subversion of both the language and the verifier. For this reason,
  58     they are all instance methods, and access to the constructor of
  59     this factory is guarded by a security check, in similar style to
  60     {@link jdk.internal.misc.Unsafe}. </P>
  61 */
  62 
  63 public class ReflectionFactory {
  64 
  65     private static boolean initted = false;
  66     private static final Permission reflectionFactoryAccessPerm
  67         = new RuntimePermission("reflectionFactoryAccess");
  68     private static final ReflectionFactory soleInstance = new ReflectionFactory();
  69     // Provides access to package-private mechanisms in java.lang.reflect
  70     private static volatile LangReflectAccess langReflectAccess;
  71 
  72     /* Method for static class initializer <clinit>, or null */
  73     private static volatile Method hasStaticInitializerMethod;
  74 
  75     //
  76     // "Inflation" mechanism. Loading bytecodes to implement
  77     // Method.invoke() and Constructor.newInstance() currently costs
  78     // 3-4x more than an invocation via native code for the first
  79     // invocation (though subsequent invocations have been benchmarked
  80     // to be over 20x faster). Unfortunately this cost increases
  81     // startup time for certain applications that use reflection
  82     // intensively (but only once per class) to bootstrap themselves.
  83     // To avoid this penalty we reuse the existing JVM entry points
  84     // for the first few invocations of Methods and Constructors and
  85     // then switch to the bytecode-based implementations.
  86     //
  87     // Package-private to be accessible to NativeMethodAccessorImpl
  88     // and NativeConstructorAccessorImpl
  89     private static boolean noInflation        = false;
  90     private static int     inflationThreshold = 15;
  91 
  92     private ReflectionFactory() {
  93     }
  94 
  95     /**
  96      * A convenience class for acquiring the capability to instantiate
  97      * reflective objects.  Use this instead of a raw call to {@link
  98      * #getReflectionFactory} in order to avoid being limited by the
  99      * permissions of your callers.
 100      *
 101      * <p>An instance of this class can be used as the argument of
 102      * <code>AccessController.doPrivileged</code>.
 103      */
 104     public static final class GetReflectionFactoryAction
 105         implements PrivilegedAction<ReflectionFactory> {
 106         public ReflectionFactory run() {
 107             return getReflectionFactory();
 108         }
 109     }
 110 
 111     /**
 112      * Provides the caller with the capability to instantiate reflective
 113      * objects.
 114      *
 115      * <p> First, if there is a security manager, its
 116      * <code>checkPermission</code> method is called with a {@link
 117      * java.lang.RuntimePermission} with target
 118      * <code>"reflectionFactoryAccess"</code>.  This may result in a
 119      * security exception.
 120      *
 121      * <p> The returned <code>ReflectionFactory</code> object should be
 122      * carefully guarded by the caller, since it can be used to read and
 123      * write private data and invoke private methods, as well as to load
 124      * unverified bytecodes.  It must never be passed to untrusted code.
 125      *
 126      * @exception SecurityException if a security manager exists and its
 127      *             <code>checkPermission</code> method doesn't allow
 128      *             access to the RuntimePermission "reflectionFactoryAccess".  */
 129     public static ReflectionFactory getReflectionFactory() {
 130         SecurityManager security = System.getSecurityManager();
 131         if (security != null) {
 132             // TO DO: security.checkReflectionFactoryAccess();
 133             security.checkPermission(reflectionFactoryAccessPerm);
 134         }
 135         return soleInstance;
 136     }
 137 
 138     /**
 139      * Returns an alternate reflective Method instance for the given method
 140      * intended for reflection to invoke, if present.
 141      *
 142      * A trusted method can define an alternate implementation for a method `foo`
 143      * by defining a method named "reflected$foo" that will be invoked
 144      * reflectively.
 145      */
 146     private static Method findMethodForReflection(Method method) {
 147         String altName = "reflected$" + method.getName();
 148         try {
 149            return method.getDeclaringClass()
 150                         .getDeclaredMethod(altName, method.getParameterTypes());
 151         } catch (NoSuchMethodException ex) {
 152             return null;
 153         }
 154     }
 155 
 156     //--------------------------------------------------------------------------
 157     //
 158     // Routines used by java.lang.reflect
 159     //
 160     //
 161 
 162     /** Called only by java.lang.reflect.Modifier's static initializer */
 163     public void setLangReflectAccess(LangReflectAccess access) {
 164         langReflectAccess = access;
 165     }
 166 
 167     /**
 168      * Note: this routine can cause the declaring class for the field
 169      * be initialized and therefore must not be called until the
 170      * first get/set of this field.
 171      * @param field the field
 172      * @param override true if caller has overridden accessibility
 173      */
 174     public FieldAccessor newFieldAccessor(Field field, boolean override) {
 175         checkInitted();
 176         return UnsafeFieldAccessorFactory.newFieldAccessor(field, override);
 177     }
 178 
 179     public MethodAccessor newMethodAccessor(Method method) {
 180         checkInitted();
 181 
 182         boolean noInflation = ReflectionFactory.noInflation;
 183         if (Reflection.isCallerSensitive(method)) {
 184             Method altMethod = findMethodForReflection(method);
 185             if (altMethod != null) {
 186                 method = altMethod;
 187             }
 188         }
 189 
 190         if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
 191             return new MethodAccessorGenerator().
 192                 generateMethod(method.getDeclaringClass(),
 193                                method.getName(),
 194                                method.getParameterTypes(),
 195                                method.getReturnType(),
 196                                method.getExceptionTypes(),
 197                                method.getModifiers());
 198         } else {
 199             NativeMethodAccessorImpl acc =
 200                 new NativeMethodAccessorImpl(method);
 201             DelegatingMethodAccessorImpl res =
 202                 new DelegatingMethodAccessorImpl(acc);
 203             acc.setParent(res);
 204             return res;
 205         }
 206     }
 207 
 208     public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {
 209         checkInitted();
 210 
 211         Class<?> declaringClass = c.getDeclaringClass();
 212         if (Modifier.isAbstract(declaringClass.getModifiers())) {
 213             return new InstantiationExceptionConstructorAccessorImpl(null);
 214         }
 215         if (declaringClass == Class.class) {
 216             return new InstantiationExceptionConstructorAccessorImpl
 217                 ("Can not instantiate java.lang.Class");
 218         }
 219         // Bootstrapping issue: since we use Class.newInstance() in
 220         // the ConstructorAccessor generation process, we have to
 221         // break the cycle here.
 222         if (Reflection.isSubclassOf(declaringClass,
 223                                     ConstructorAccessorImpl.class)) {
 224             return new BootstrapConstructorAccessorImpl(c);
 225         }
 226 
 227         if (noInflation && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
 228             return new MethodAccessorGenerator().
 229                 generateConstructor(c.getDeclaringClass(),
 230                                     c.getParameterTypes(),
 231                                     c.getExceptionTypes(),
 232                                     c.getModifiers());
 233         } else {
 234             NativeConstructorAccessorImpl acc =
 235                 new NativeConstructorAccessorImpl(c);
 236             DelegatingConstructorAccessorImpl res =
 237                 new DelegatingConstructorAccessorImpl(acc);
 238             acc.setParent(res);
 239             return res;
 240         }
 241     }
 242 
 243     //--------------------------------------------------------------------------
 244     //
 245     // Routines used by java.lang
 246     //
 247     //
 248 
 249     /** Creates a new java.lang.reflect.Field. Access checks as per
 250         java.lang.reflect.AccessibleObject are not overridden. */
 251     public Field newField(Class<?> declaringClass,
 252                           String name,
 253                           Class<?> type,
 254                           int modifiers,
 255                           int slot,
 256                           String signature,
 257                           byte[] annotations)
 258     {
 259         return langReflectAccess().newField(declaringClass,
 260                                             name,
 261                                             type,
 262                                             modifiers,
 263                                             slot,
 264                                             signature,
 265                                             annotations);
 266     }
 267 
 268     /** Creates a new java.lang.reflect.Method. Access checks as per
 269         java.lang.reflect.AccessibleObject are not overridden. */
 270     public Method newMethod(Class<?> declaringClass,
 271                             String name,
 272                             Class<?>[] parameterTypes,
 273                             Class<?> returnType,
 274                             Class<?>[] checkedExceptions,
 275                             int modifiers,
 276                             int slot,
 277                             String signature,
 278                             byte[] annotations,
 279                             byte[] parameterAnnotations,
 280                             byte[] annotationDefault)
 281     {
 282         return langReflectAccess().newMethod(declaringClass,
 283                                              name,
 284                                              parameterTypes,
 285                                              returnType,
 286                                              checkedExceptions,
 287                                              modifiers,
 288                                              slot,
 289                                              signature,
 290                                              annotations,
 291                                              parameterAnnotations,
 292                                              annotationDefault);
 293     }
 294 
 295     /** Creates a new java.lang.reflect.Constructor. Access checks as
 296         per java.lang.reflect.AccessibleObject are not overridden. */
 297     public Constructor<?> newConstructor(Class<?> declaringClass,
 298                                          Class<?>[] parameterTypes,
 299                                          Class<?>[] checkedExceptions,
 300                                          int modifiers,
 301                                          int slot,
 302                                          String signature,
 303                                          byte[] annotations,
 304                                          byte[] parameterAnnotations)
 305     {
 306         return langReflectAccess().newConstructor(declaringClass,
 307                                                   parameterTypes,
 308                                                   checkedExceptions,
 309                                                   modifiers,
 310                                                   slot,
 311                                                   signature,
 312                                                   annotations,
 313                                                   parameterAnnotations);
 314     }
 315 
 316     /** Gets the MethodAccessor object for a java.lang.reflect.Method */
 317     public MethodAccessor getMethodAccessor(Method m) {
 318         return langReflectAccess().getMethodAccessor(m);
 319     }
 320 
 321     /** Sets the MethodAccessor object for a java.lang.reflect.Method */
 322     public void setMethodAccessor(Method m, MethodAccessor accessor) {
 323         langReflectAccess().setMethodAccessor(m, accessor);
 324     }
 325 
 326     /** Gets the ConstructorAccessor object for a
 327         java.lang.reflect.Constructor */
 328     public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {
 329         return langReflectAccess().getConstructorAccessor(c);
 330     }
 331 
 332     /** Sets the ConstructorAccessor object for a
 333         java.lang.reflect.Constructor */
 334     public void setConstructorAccessor(Constructor<?> c,
 335                                        ConstructorAccessor accessor)
 336     {
 337         langReflectAccess().setConstructorAccessor(c, accessor);
 338     }
 339 
 340     /** Makes a copy of the passed method. The returned method is a
 341         "child" of the passed one; see the comments in Method.java for
 342         details. */
 343     public Method copyMethod(Method arg) {
 344         return langReflectAccess().copyMethod(arg);
 345     }
 346 
 347     /** Makes a copy of the passed method. The returned method is NOT
 348      * a "child" but a "sibling" of the Method in arg. Should only be
 349      * used on non-root methods. */
 350     public Method leafCopyMethod(Method arg) {
 351         return langReflectAccess().leafCopyMethod(arg);
 352     }
 353 
 354 
 355     /** Makes a copy of the passed field. The returned field is a
 356         "child" of the passed one; see the comments in Field.java for
 357         details. */
 358     public Field copyField(Field arg) {
 359         return langReflectAccess().copyField(arg);
 360     }
 361 
 362     /** Makes a copy of the passed constructor. The returned
 363         constructor is a "child" of the passed one; see the comments
 364         in Constructor.java for details. */
 365     public <T> Constructor<T> copyConstructor(Constructor<T> arg) {
 366         return langReflectAccess().copyConstructor(arg);
 367     }
 368 
 369     /** Gets the byte[] that encodes TypeAnnotations on an executable.
 370      */
 371     public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
 372         return langReflectAccess().getExecutableTypeAnnotationBytes(ex);
 373     }
 374 
 375     public Class<?>[] getExecutableSharedParameterTypes(Executable ex) {
 376         return langReflectAccess().getExecutableSharedParameterTypes(ex);
 377     }
 378 
 379     //--------------------------------------------------------------------------
 380     //
 381     // Routines used by serialization
 382     //
 383     //
 384 
 385     public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
 386         if (!Externalizable.class.isAssignableFrom(cl)) {
 387             return null;
 388         }
 389         try {
 390             Constructor<?> cons = cl.getConstructor();
 391             cons.setAccessible(true);
 392             return cons;
 393         } catch (NoSuchMethodException ex) {
 394             return null;
 395         }
 396     }
 397 
 398     public final Constructor<?> newConstructorForSerialization(Class<?> cl,
 399                                                                Constructor<?> constructorToCall)
 400     {
 401         if (constructorToCall.getDeclaringClass() == cl) {
 402             constructorToCall.setAccessible(true);
 403             return constructorToCall;
 404         }
 405         return generateConstructor(cl, constructorToCall);
 406     }
 407 
 408     public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
 409         Class<?> initCl = cl;
 410         while (Serializable.class.isAssignableFrom(initCl)) {
 411             if ((initCl = initCl.getSuperclass()) == null) {
 412                 return null;
 413             }
 414         }
 415         Constructor<?> constructorToCall;
 416         try {
 417             constructorToCall = initCl.getDeclaredConstructor();
 418             int mods = constructorToCall.getModifiers();
 419             if ((mods & Modifier.PRIVATE) != 0 ||
 420                     ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
 421                             !packageEquals(cl, initCl))) {
 422                 return null;
 423             }
 424         } catch (NoSuchMethodException ex) {
 425             return null;
 426         }
 427         return generateConstructor(cl, constructorToCall);
 428     }
 429 
 430     private final Constructor<?> generateConstructor(Class<?> cl,
 431                                                      Constructor<?> constructorToCall) {
 432 
 433 
 434         ConstructorAccessor acc = new MethodAccessorGenerator().
 435             generateSerializationConstructor(cl,
 436                                              constructorToCall.getParameterTypes(),
 437                                              constructorToCall.getExceptionTypes(),
 438                                              constructorToCall.getModifiers(),
 439                                              constructorToCall.getDeclaringClass());
 440         Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(),
 441                                           constructorToCall.getParameterTypes(),
 442                                           constructorToCall.getExceptionTypes(),
 443                                           constructorToCall.getModifiers(),
 444                                           langReflectAccess().
 445                                           getConstructorSlot(constructorToCall),
 446                                           langReflectAccess().
 447                                           getConstructorSignature(constructorToCall),
 448                                           langReflectAccess().
 449                                           getConstructorAnnotations(constructorToCall),
 450                                           langReflectAccess().
 451                                           getConstructorParameterAnnotations(constructorToCall));
 452         setConstructorAccessor(c, acc);
 453         c.setAccessible(true);
 454         return c;
 455     }
 456 
 457     public final MethodHandle readObjectForSerialization(Class<?> cl) {
 458         return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
 459     }
 460 
 461     public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
 462         return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
 463     }
 464 
 465     public final MethodHandle writeObjectForSerialization(Class<?> cl) {
 466         return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
 467     }
 468 
 469     private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
 470                                                                    String methodName,
 471                                                                    Class<?> streamClass) {
 472         if (!Serializable.class.isAssignableFrom(cl)) {
 473             return null;
 474         }
 475 
 476         try {
 477             Method meth = cl.getDeclaredMethod(methodName, streamClass);
 478             int mods = meth.getModifiers();
 479             if (meth.getReturnType() != Void.TYPE ||
 480                     Modifier.isStatic(mods) ||
 481                     !Modifier.isPrivate(mods)) {
 482                 return null;
 483             }
 484             meth.setAccessible(true);
 485             return MethodHandles.lookup().unreflect(meth);
 486         } catch (NoSuchMethodException ex) {
 487             return null;
 488         } catch (IllegalAccessException ex1) {
 489             throw new InternalError("Error", ex1);
 490         }
 491     }
 492 
 493     /**
 494      * Returns a MethodHandle for {@code writeReplace} on the serializable class
 495      * or null if no match found.
 496      * @param cl a serializable class
 497      * @returnss the {@code writeReplace} MethodHandle or {@code null} if not found
 498      */
 499     public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
 500         return getReplaceResolveForSerialization(cl, "writeReplace");
 501     }
 502 
 503     /**
 504      * Returns a MethodHandle for {@code readResolve} on the serializable class
 505      * or null if no match found.
 506      * @param cl a serializable class
 507      * @returns the {@code writeReplace} MethodHandle or {@code null} if not found
 508      */
 509     public final MethodHandle readResolveForSerialization(Class<?> cl) {
 510         return getReplaceResolveForSerialization(cl, "readResolve");
 511     }
 512 
 513     /**
 514      * Lookup readResolve or writeReplace on a class with specified
 515      * signature constraints.
 516      * @param cl a serializable class
 517      * @param methodName the method name to find
 518      * @returns a MethodHandle for the method or {@code null} if not found or
 519      *       has the wrong signature.
 520      */
 521     private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
 522                                                            String methodName) {
 523         if (!Serializable.class.isAssignableFrom(cl)) {
 524             return null;
 525         }
 526 
 527         Class<?> defCl = cl;
 528         while (defCl != null) {
 529             try {
 530                 Method m = defCl.getDeclaredMethod(methodName);
 531                 if (m.getReturnType() != Object.class) {
 532                     return null;
 533                 }
 534                 int mods = m.getModifiers();
 535                 if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
 536                     return null;
 537                 } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
 538                     // fall through
 539                 } else if (Modifier.isPrivate(mods) && (cl != defCl)) {
 540                     return null;
 541                 } else if (!packageEquals(cl, defCl)) {
 542                     return null;
 543                 }
 544                 try {
 545                     // Normal return
 546                     m.setAccessible(true);
 547                     return MethodHandles.lookup().unreflect(m);
 548                 } catch (IllegalAccessException ex0) {
 549                     // setAccessible should prevent IAE
 550                     throw new InternalError("Error", ex0);
 551                 }
 552             } catch (NoSuchMethodException ex) {
 553                 defCl = defCl.getSuperclass();
 554             }
 555         }
 556         return null;
 557     }
 558 
 559     /**
 560      * Returns true if the given class defines a static initializer method,
 561      * false otherwise.
 562      */
 563     public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
 564         Method m = hasStaticInitializerMethod;
 565         if (m == null) {
 566             try {
 567                 m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
 568                         new Class<?>[]{Class.class});
 569                 m.setAccessible(true);
 570                 hasStaticInitializerMethod = m;
 571             } catch (NoSuchMethodException ex) {
 572                 throw new InternalError("No such method hasStaticInitializer on "
 573                         + ObjectStreamClass.class, ex);
 574             }
 575         }
 576         try {
 577             return (Boolean) m.invoke(null, cl);
 578         } catch (InvocationTargetException | IllegalAccessException ex) {
 579             throw new InternalError("Exception invoking hasStaticInitializer", ex);
 580         }
 581     }
 582 
 583     /**
 584      * Return the accessible constructor for OptionalDataException signaling eof.
 585      * @returns the eof constructor for OptionalDataException
 586      */
 587     public final Constructor<OptionalDataException> newOptionalDataExceptionForSerialization() {
 588         try {
 589             Constructor<OptionalDataException> boolCtor =
 590                     OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
 591             boolCtor.setAccessible(true);
 592             return boolCtor;
 593         } catch (NoSuchMethodException ex) {
 594             throw new InternalError("Constructor not found", ex);
 595         }
 596     }
 597 
 598     //--------------------------------------------------------------------------
 599     //
 600     // Internals only below this point
 601     //
 602 
 603     static int inflationThreshold() {
 604         return inflationThreshold;
 605     }
 606 
 607     /** We have to defer full initialization of this class until after
 608         the static initializer is run since java.lang.reflect.Method's
 609         static initializer (more properly, that for
 610         java.lang.reflect.AccessibleObject) causes this class's to be
 611         run, before the system properties are set up. */
 612     private static void checkInitted() {
 613         if (initted) return;
 614 
 615         // Defer initialization until module system is initialized so as
 616         // to avoid inflation and spinning bytecode in unnamed modules
 617         // during early startup.
 618         if (!VM.isModuleSystemInited()) {
 619             return;
 620         }
 621 
 622         Properties props = GetPropertyAction.privilegedGetProperties();
 623         String val = props.getProperty("sun.reflect.noInflation");
 624         if (val != null && val.equals("true")) {
 625             noInflation = true;
 626         }
 627 
 628         val = props.getProperty("sun.reflect.inflationThreshold");
 629         if (val != null) {
 630             try {
 631                 inflationThreshold = Integer.parseInt(val);
 632             } catch (NumberFormatException e) {
 633                 throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
 634             }
 635         }
 636 
 637         initted = true;
 638     }
 639 
 640     private static LangReflectAccess langReflectAccess() {
 641         if (langReflectAccess == null) {
 642             // Call a static method to get class java.lang.reflect.Modifier
 643             // initialized. Its static initializer will cause
 644             // setLangReflectAccess() to be called from the context of the
 645             // java.lang.reflect package.
 646             Modifier.isPublic(Modifier.PUBLIC);
 647         }
 648         return langReflectAccess;
 649     }
 650 
 651     /**
 652      * Returns true if classes are defined in the classloader and same package, false
 653      * otherwise.
 654      * @param cl1 a class
 655      * @param cl2 another class
 656      * @returns true if the two classes are in the same classloader and package
 657      */
 658     private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
 659         return cl1.getClassLoader() == cl2.getClassLoader() &&
 660                 Objects.equals(cl1.getPackage(), cl2.getPackage());
 661     }
 662 
 663 }