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