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         if (Reflection.isCallerSensitive(method)) {
 183             Method altMethod = findMethodForReflection(method);
 184             if (altMethod != null) {
 185                 method = altMethod;
 186             }
 187         }
 188 
 189         if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
 190             return new MethodAccessorGenerator().
 191                 generateMethod(method.getDeclaringClass(),
 192                                method.getName(),
 193                                method.getParameterTypes(),
 194                                method.getReturnType(),
 195                                method.getExceptionTypes(),
 196                                method.getModifiers());
 197         } else {
 198             NativeMethodAccessorImpl acc =
 199                 new NativeMethodAccessorImpl(method);
 200             DelegatingMethodAccessorImpl res =
 201                 new DelegatingMethodAccessorImpl(acc);
 202             acc.setParent(res);
 203             return res;
 204         }
 205     }
 206 
 207     public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {
 208         checkInitted();
 209 
 210         Class<?> declaringClass = c.getDeclaringClass();
 211         if (Modifier.isAbstract(declaringClass.getModifiers())) {
 212             return new InstantiationExceptionConstructorAccessorImpl(null);
 213         }
 214         if (declaringClass == Class.class) {
 215             return new InstantiationExceptionConstructorAccessorImpl
 216                 ("Can not instantiate java.lang.Class");
 217         }
 218         // Bootstrapping issue: since we use Class.newInstance() in
 219         // the ConstructorAccessor generation process, we have to
 220         // break the cycle here.
 221         if (Reflection.isSubclassOf(declaringClass,
 222                                     ConstructorAccessorImpl.class)) {
 223             return new BootstrapConstructorAccessorImpl(c);
 224         }
 225 
 226         if (noInflation && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
 227             return new MethodAccessorGenerator().
 228                 generateConstructor(c.getDeclaringClass(),
 229                                     c.getParameterTypes(),
 230                                     c.getExceptionTypes(),
 231                                     c.getModifiers());
 232         } else {
 233             NativeConstructorAccessorImpl acc =
 234                 new NativeConstructorAccessorImpl(c);
 235             DelegatingConstructorAccessorImpl res =
 236                 new DelegatingConstructorAccessorImpl(acc);
 237             acc.setParent(res);
 238             return res;
 239         }
 240     }
 241 
 242     //--------------------------------------------------------------------------
 243     //
 244     // Routines used by java.lang
 245     //
 246     //
 247 
 248     /** Creates a new java.lang.reflect.Field. Access checks as per
 249         java.lang.reflect.AccessibleObject are not overridden. */
 250     public Field newField(Class<?> declaringClass,
 251                           String name,
 252                           Class<?> type,
 253                           int modifiers,
 254                           int slot,
 255                           String signature,
 256                           byte[] annotations)
 257     {
 258         return langReflectAccess().newField(declaringClass,
 259                                             name,
 260                                             type,
 261                                             modifiers,
 262                                             slot,
 263                                             signature,
 264                                             annotations);
 265     }
 266 
 267     /** Creates a new java.lang.reflect.Method. Access checks as per
 268         java.lang.reflect.AccessibleObject are not overridden. */
 269     public Method newMethod(Class<?> declaringClass,
 270                             String name,
 271                             Class<?>[] parameterTypes,
 272                             Class<?> returnType,
 273                             Class<?>[] checkedExceptions,
 274                             int modifiers,
 275                             int slot,
 276                             String signature,
 277                             byte[] annotations,
 278                             byte[] parameterAnnotations,
 279                             byte[] annotationDefault)
 280     {
 281         return langReflectAccess().newMethod(declaringClass,
 282                                              name,
 283                                              parameterTypes,
 284                                              returnType,
 285                                              checkedExceptions,
 286                                              modifiers,
 287                                              slot,
 288                                              signature,
 289                                              annotations,
 290                                              parameterAnnotations,
 291                                              annotationDefault);
 292     }
 293 
 294     /** Creates a new java.lang.reflect.Constructor. Access checks as
 295         per java.lang.reflect.AccessibleObject are not overridden. */
 296     public Constructor<?> newConstructor(Class<?> declaringClass,
 297                                          Class<?>[] parameterTypes,
 298                                          Class<?>[] checkedExceptions,
 299                                          int modifiers,
 300                                          int slot,
 301                                          String signature,
 302                                          byte[] annotations,
 303                                          byte[] parameterAnnotations)
 304     {
 305         return langReflectAccess().newConstructor(declaringClass,
 306                                                   parameterTypes,
 307                                                   checkedExceptions,
 308                                                   modifiers,
 309                                                   slot,
 310                                                   signature,
 311                                                   annotations,
 312                                                   parameterAnnotations);
 313     }
 314 
 315     /** Gets the MethodAccessor object for a java.lang.reflect.Method */
 316     public MethodAccessor getMethodAccessor(Method m) {
 317         return langReflectAccess().getMethodAccessor(m);
 318     }
 319 
 320     /** Sets the MethodAccessor object for a java.lang.reflect.Method */
 321     public void setMethodAccessor(Method m, MethodAccessor accessor) {
 322         langReflectAccess().setMethodAccessor(m, accessor);
 323     }
 324 
 325     /** Gets the ConstructorAccessor object for a
 326         java.lang.reflect.Constructor */
 327     public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {
 328         return langReflectAccess().getConstructorAccessor(c);
 329     }
 330 
 331     /** Sets the ConstructorAccessor object for a
 332         java.lang.reflect.Constructor */
 333     public void setConstructorAccessor(Constructor<?> c,
 334                                        ConstructorAccessor accessor)
 335     {
 336         langReflectAccess().setConstructorAccessor(c, accessor);
 337     }
 338 
 339     /** Makes a copy of the passed method. The returned method is a
 340         "child" of the passed one; see the comments in Method.java for
 341         details. */
 342     public Method copyMethod(Method arg) {
 343         return langReflectAccess().copyMethod(arg);
 344     }
 345 
 346     /** Makes a copy of the passed method. The returned method is NOT
 347      * a "child" but a "sibling" of the Method in arg. Should only be
 348      * used on non-root methods. */
 349     public Method leafCopyMethod(Method arg) {
 350         return langReflectAccess().leafCopyMethod(arg);
 351     }
 352 
 353 
 354     /** Makes a copy of the passed field. The returned field is a
 355         "child" of the passed one; see the comments in Field.java for
 356         details. */
 357     public Field copyField(Field arg) {
 358         return langReflectAccess().copyField(arg);
 359     }
 360 
 361     /** Makes a copy of the passed constructor. The returned
 362         constructor is a "child" of the passed one; see the comments
 363         in Constructor.java for details. */
 364     public <T> Constructor<T> copyConstructor(Constructor<T> arg) {
 365         return langReflectAccess().copyConstructor(arg);
 366     }
 367 
 368     /** Gets the byte[] that encodes TypeAnnotations on an executable.
 369      */
 370     public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
 371         return langReflectAccess().getExecutableTypeAnnotationBytes(ex);
 372     }
 373 
 374     public Class<?>[] getExecutableSharedParameterTypes(Executable ex) {
 375         return langReflectAccess().getExecutableSharedParameterTypes(ex);
 376     }
 377 
 378     //--------------------------------------------------------------------------
 379     //
 380     // Routines used by serialization
 381     //
 382     //
 383 
 384     public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
 385         if (!Externalizable.class.isAssignableFrom(cl)) {
 386             return null;
 387         }
 388         try {
 389             Constructor<?> cons = cl.getConstructor();
 390             cons.setAccessible(true);
 391             return cons;
 392         } catch (NoSuchMethodException ex) {
 393             return null;
 394         }
 395     }
 396 
 397     public final Constructor<?> newConstructorForSerialization(Class<?> cl,
 398                                                                Constructor<?> constructorToCall)
 399     {
 400         if (constructorToCall.getDeclaringClass() == cl) {
 401             constructorToCall.setAccessible(true);
 402             return constructorToCall;
 403         }
 404         return generateConstructor(cl, constructorToCall);
 405     }
 406 
 407     public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
 408         Class<?> initCl = cl;
 409         while (Serializable.class.isAssignableFrom(initCl)) {
 410             if ((initCl = initCl.getSuperclass()) == null) {
 411                 return null;
 412             }
 413         }
 414         Constructor<?> constructorToCall;
 415         try {
 416             constructorToCall = initCl.getDeclaredConstructor();
 417             int mods = constructorToCall.getModifiers();
 418             if ((mods & Modifier.PRIVATE) != 0 ||
 419                     ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
 420                             !packageEquals(cl, initCl))) {
 421                 return null;
 422             }
 423         } catch (NoSuchMethodException ex) {
 424             return null;
 425         }
 426         return generateConstructor(cl, constructorToCall);
 427     }
 428 
 429     private final Constructor<?> generateConstructor(Class<?> cl,
 430                                                      Constructor<?> constructorToCall) {
 431 
 432 
 433         ConstructorAccessor acc = new MethodAccessorGenerator().
 434             generateSerializationConstructor(cl,
 435                                              constructorToCall.getParameterTypes(),
 436                                              constructorToCall.getExceptionTypes(),
 437                                              constructorToCall.getModifiers(),
 438                                              constructorToCall.getDeclaringClass());
 439         Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(),
 440                                           constructorToCall.getParameterTypes(),
 441                                           constructorToCall.getExceptionTypes(),
 442                                           constructorToCall.getModifiers(),
 443                                           langReflectAccess().
 444                                           getConstructorSlot(constructorToCall),
 445                                           langReflectAccess().
 446                                           getConstructorSignature(constructorToCall),
 447                                           langReflectAccess().
 448                                           getConstructorAnnotations(constructorToCall),
 449                                           langReflectAccess().
 450                                           getConstructorParameterAnnotations(constructorToCall));
 451         setConstructorAccessor(c, acc);
 452         c.setAccessible(true);
 453         return c;
 454     }
 455 
 456     public final MethodHandle readObjectForSerialization(Class<?> cl) {
 457         return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
 458     }
 459 
 460     public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
 461         return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
 462     }
 463 
 464     public final MethodHandle writeObjectForSerialization(Class<?> cl) {
 465         return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
 466     }
 467 
 468     private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
 469                                                                    String methodName,
 470                                                                    Class<?> streamClass) {
 471         if (!Serializable.class.isAssignableFrom(cl)) {
 472             return null;
 473         }
 474 
 475         try {
 476             Method meth = cl.getDeclaredMethod(methodName, streamClass);
 477             int mods = meth.getModifiers();
 478             if (meth.getReturnType() != Void.TYPE ||
 479                     Modifier.isStatic(mods) ||
 480                     !Modifier.isPrivate(mods)) {
 481                 return null;
 482             }
 483             meth.setAccessible(true);
 484             return MethodHandles.lookup().unreflect(meth);
 485         } catch (NoSuchMethodException ex) {
 486             return null;
 487         } catch (IllegalAccessException ex1) {
 488             throw new InternalError("Error", ex1);
 489         }
 490     }
 491 
 492     /**
 493      * Returns a MethodHandle for {@code writeReplace} on the serializable class
 494      * or null if no match found.
 495      * @param cl a serializable class
 496      * @returnss the {@code writeReplace} MethodHandle or {@code null} if not found
 497      */
 498     public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
 499         return getReplaceResolveForSerialization(cl, "writeReplace");
 500     }
 501 
 502     /**
 503      * Returns a MethodHandle for {@code readResolve} on the serializable class
 504      * or null if no match found.
 505      * @param cl a serializable class
 506      * @returns the {@code writeReplace} MethodHandle or {@code null} if not found
 507      */
 508     public final MethodHandle readResolveForSerialization(Class<?> cl) {
 509         return getReplaceResolveForSerialization(cl, "readResolve");
 510     }
 511 
 512     /**
 513      * Lookup readResolve or writeReplace on a class with specified
 514      * signature constraints.
 515      * @param cl a serializable class
 516      * @param methodName the method name to find
 517      * @returns a MethodHandle for the method or {@code null} if not found or
 518      *       has the wrong signature.
 519      */
 520     private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
 521                                                            String methodName) {
 522         if (!Serializable.class.isAssignableFrom(cl)) {
 523             return null;
 524         }
 525 
 526         Class<?> defCl = cl;
 527         while (defCl != null) {
 528             try {
 529                 Method m = defCl.getDeclaredMethod(methodName);
 530                 if (m.getReturnType() != Object.class) {
 531                     return null;
 532                 }
 533                 int mods = m.getModifiers();
 534                 if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
 535                     return null;
 536                 } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
 537                     // fall through
 538                 } else if (Modifier.isPrivate(mods) && (cl != defCl)) {
 539                     return null;
 540                 } else if (!packageEquals(cl, defCl)) {
 541                     return null;
 542                 }
 543                 try {
 544                     // Normal return
 545                     m.setAccessible(true);
 546                     return MethodHandles.lookup().unreflect(m);
 547                 } catch (IllegalAccessException ex0) {
 548                     // setAccessible should prevent IAE
 549                     throw new InternalError("Error", ex0);
 550                 }
 551             } catch (NoSuchMethodException ex) {
 552                 defCl = defCl.getSuperclass();
 553             }
 554         }
 555         return null;
 556     }
 557 
 558     /**
 559      * Returns true if the given class defines a static initializer method,
 560      * false otherwise.
 561      */
 562     public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
 563         Method m = hasStaticInitializerMethod;
 564         if (m == null) {
 565             try {
 566                 m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
 567                         new Class<?>[]{Class.class});
 568                 m.setAccessible(true);
 569                 hasStaticInitializerMethod = m;
 570             } catch (NoSuchMethodException ex) {
 571                 throw new InternalError("No such method hasStaticInitializer on "
 572                         + ObjectStreamClass.class, ex);
 573             }
 574         }
 575         try {
 576             return (Boolean) m.invoke(null, cl);
 577         } catch (InvocationTargetException | IllegalAccessException ex) {
 578             throw new InternalError("Exception invoking hasStaticInitializer", ex);
 579         }
 580     }
 581 
 582     /**
 583      * Return the accessible constructor for OptionalDataException signaling eof.
 584      * @returns the eof constructor for OptionalDataException
 585      */
 586     public final Constructor<OptionalDataException> newOptionalDataExceptionForSerialization() {
 587         try {
 588             Constructor<OptionalDataException> boolCtor =
 589                     OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
 590             boolCtor.setAccessible(true);
 591             return boolCtor;
 592         } catch (NoSuchMethodException ex) {
 593             throw new InternalError("Constructor not found", ex);
 594         }
 595     }
 596 
 597     //--------------------------------------------------------------------------
 598     //
 599     // Internals only below this point
 600     //
 601 
 602     static int inflationThreshold() {
 603         return inflationThreshold;
 604     }
 605 
 606     /** We have to defer full initialization of this class until after
 607         the static initializer is run since java.lang.reflect.Method's
 608         static initializer (more properly, that for
 609         java.lang.reflect.AccessibleObject) causes this class's to be
 610         run, before the system properties are set up. */
 611     private static void checkInitted() {
 612         if (initted) return;
 613 
 614         // Defer initialization until module system is initialized so as
 615         // to avoid inflation and spinning bytecode in unnamed modules
 616         // during early startup.
 617         if (!VM.isModuleSystemInited()) {
 618             return;
 619         }
 620 
 621         Properties props = GetPropertyAction.privilegedGetProperties();
 622         String val = props.getProperty("sun.reflect.noInflation");
 623         if (val != null && val.equals("true")) {
 624             noInflation = true;
 625         }
 626 
 627         val = props.getProperty("sun.reflect.inflationThreshold");
 628         if (val != null) {
 629             try {
 630                 inflationThreshold = Integer.parseInt(val);
 631             } catch (NumberFormatException e) {
 632                 throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
 633             }
 634         }
 635 
 636         initted = true;
 637     }
 638 
 639     private static LangReflectAccess langReflectAccess() {
 640         if (langReflectAccess == null) {
 641             // Call a static method to get class java.lang.reflect.Modifier
 642             // initialized. Its static initializer will cause
 643             // setLangReflectAccess() to be called from the context of the
 644             // java.lang.reflect package.
 645             Modifier.isPublic(Modifier.PUBLIC);
 646         }
 647         return langReflectAccess;
 648     }
 649 
 650     /**
 651      * Returns true if classes are defined in the classloader and same package, false
 652      * otherwise.
 653      * @param cl1 a class
 654      * @param cl2 another class
 655      * @returns true if the two classes are in the same classloader and package
 656      */
 657     private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
 658         return cl1.getClassLoader() == cl2.getClassLoader() &&
 659                 Objects.equals(cl1.getPackage(), cl2.getPackage());
 660     }
 661 
 662 }