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