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