1 /*
   2  * Copyright (c) 2001, 2020, 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 overridden
 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().isHidden()
 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().isHidden()
 249                 && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
 250             return new MethodAccessorGenerator().
 251                 generateConstructor(c.getDeclaringClass(),
 252                                     c.getParameterTypes(),
 253                                     c.getExceptionTypes(),
 254                                     c.getModifiers());
 255         } else {
 256             NativeConstructorAccessorImpl acc =
 257                 new NativeConstructorAccessorImpl(c);
 258             DelegatingConstructorAccessorImpl res =
 259                 new DelegatingConstructorAccessorImpl(acc);
 260             acc.setParent(res);
 261             return res;
 262         }
 263     }
 264 
 265     //--------------------------------------------------------------------------
 266     //
 267     // Routines used by java.lang
 268     //
 269     //
 270 
 271     /** Creates a new java.lang.reflect.Constructor. Access checks as
 272         per java.lang.reflect.AccessibleObject are not overridden. */
 273     public Constructor<?> newConstructor(Class<?> declaringClass,
 274                                          Class<?>[] parameterTypes,
 275                                          Class<?>[] checkedExceptions,
 276                                          int modifiers,
 277                                          int slot,
 278                                          String signature,
 279                                          byte[] annotations,
 280                                          byte[] parameterAnnotations)
 281     {
 282         return langReflectAccess.newConstructor(declaringClass,
 283                                                 parameterTypes,
 284                                                 checkedExceptions,
 285                                                 modifiers,
 286                                                 slot,
 287                                                 signature,
 288                                                 annotations,
 289                                                 parameterAnnotations);
 290     }
 291 
 292     /** Gets the ConstructorAccessor object for a
 293         java.lang.reflect.Constructor */
 294     public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {
 295         return langReflectAccess.getConstructorAccessor(c);
 296     }
 297 
 298     /** Sets the ConstructorAccessor object for a
 299         java.lang.reflect.Constructor */
 300     public void setConstructorAccessor(Constructor<?> c,
 301                                        ConstructorAccessor accessor)
 302     {
 303         langReflectAccess.setConstructorAccessor(c, accessor);
 304     }
 305 
 306     /** Makes a copy of the passed method. The returned method is a
 307         "child" of the passed one; see the comments in Method.java for
 308         details. */
 309     public Method copyMethod(Method arg) {
 310         return langReflectAccess.copyMethod(arg);
 311     }
 312 
 313     /** Makes a copy of the passed method. The returned method is NOT
 314      * a "child" but a "sibling" of the Method in arg. Should only be
 315      * used on non-root methods. */
 316     public Method leafCopyMethod(Method arg) {
 317         return langReflectAccess.leafCopyMethod(arg);
 318     }
 319 
 320 
 321     /** Makes a copy of the passed field. The returned field is a
 322         "child" of the passed one; see the comments in Field.java for
 323         details. */
 324     public Field copyField(Field arg) {
 325         return langReflectAccess.copyField(arg);
 326     }
 327 
 328     /** Makes a copy of the passed constructor. The returned
 329         constructor is a "child" of the passed one; see the comments
 330         in Constructor.java for details. */
 331     public <T> Constructor<T> copyConstructor(Constructor<T> arg) {
 332         return langReflectAccess.copyConstructor(arg);
 333     }
 334 
 335     /** Gets the byte[] that encodes TypeAnnotations on an executable.
 336      */
 337     public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
 338         return langReflectAccess.getExecutableTypeAnnotationBytes(ex);
 339     }
 340 
 341     public Class<?>[] getExecutableSharedParameterTypes(Executable ex) {
 342         return langReflectAccess.getExecutableSharedParameterTypes(ex);
 343     }
 344 
 345     public <T> T newInstance(Constructor<T> ctor, Object[] args, Class<?> caller)
 346         throws IllegalAccessException, InstantiationException, InvocationTargetException
 347     {
 348         return langReflectAccess.newInstance(ctor, args, caller);
 349     }
 350 
 351     //--------------------------------------------------------------------------
 352     //
 353     // Routines used by serialization
 354     //
 355     //
 356 
 357     public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
 358         if (!Externalizable.class.isAssignableFrom(cl)) {
 359             return null;
 360         }
 361         try {
 362             Constructor<?> cons = cl.getConstructor();
 363             cons.setAccessible(true);
 364             return cons;
 365         } catch (NoSuchMethodException ex) {
 366             return null;
 367         }
 368     }
 369 
 370     public final Constructor<?> newConstructorForSerialization(Class<?> cl,
 371                                                                Constructor<?> constructorToCall)
 372     {
 373         if (constructorToCall.getDeclaringClass() == cl) {
 374             constructorToCall.setAccessible(true);
 375             return constructorToCall;
 376         }
 377         return generateConstructor(cl, constructorToCall);
 378     }
 379 
 380     /**
 381      * Given a class, determines whether its superclass has
 382      * any constructors that are accessible from the class.
 383      * This is a special purpose method intended to do access
 384      * checking for a serializable class and its superclasses
 385      * up to, but not including, the first non-serializable
 386      * superclass. This also implies that the superclass is
 387      * always non-null, because a serializable class must be a
 388      * class (not an interface) and Object is not serializable.
 389      *
 390      * @param cl the class from which access is checked
 391      * @return whether the superclass has a constructor accessible from cl
 392      */
 393     private boolean superHasAccessibleConstructor(Class<?> cl) {
 394         Class<?> superCl = cl.getSuperclass();
 395         assert Serializable.class.isAssignableFrom(cl);
 396         assert superCl != null;
 397         if (packageEquals(cl, superCl)) {
 398             // accessible if any non-private constructor is found
 399             for (Constructor<?> ctor : superCl.getDeclaredConstructors()) {
 400                 if ((ctor.getModifiers() & Modifier.PRIVATE) == 0) {
 401                     return true;
 402                 }
 403             }
 404             if (Reflection.areNestMates(cl, superCl)) {
 405                 return true;
 406             }
 407             return false;
 408         } else {
 409             // sanity check to ensure the parent is protected or public
 410             if ((superCl.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) {
 411                 return false;
 412             }
 413             // accessible if any constructor is protected or public
 414             for (Constructor<?> ctor : superCl.getDeclaredConstructors()) {
 415                 if ((ctor.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0) {
 416                     return true;
 417                 }
 418             }
 419             return false;
 420         }
 421     }
 422 
 423     /**
 424      * Returns a constructor that allocates an instance of cl and that then initializes
 425      * the instance by calling the no-arg constructor of its first non-serializable
 426      * superclass. This is specified in the Serialization Specification, section 3.1,
 427      * in step 11 of the deserialization process. If cl is not serializable, returns
 428      * cl's no-arg constructor. If no accessible constructor is found, or if the
 429      * class hierarchy is somehow malformed (e.g., a serializable class has no
 430      * superclass), null is returned.
 431      *
 432      * @param cl the class for which a constructor is to be found
 433      * @return the generated constructor, or null if none is available
 434      */
 435     public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
 436         Class<?> initCl = cl;
 437         while (Serializable.class.isAssignableFrom(initCl)) {
 438             Class<?> prev = initCl;
 439             if ((initCl = initCl.getSuperclass()) == null ||
 440                 (!disableSerialConstructorChecks && !superHasAccessibleConstructor(prev))) {
 441                 return null;
 442             }
 443         }
 444         Constructor<?> constructorToCall;
 445         try {
 446             constructorToCall = initCl.getDeclaredConstructor();
 447             int mods = constructorToCall.getModifiers();
 448             if ((mods & Modifier.PRIVATE) != 0 ||
 449                     ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
 450                             !packageEquals(cl, initCl))) {
 451                 return null;
 452             }
 453         } catch (NoSuchMethodException ex) {
 454             return null;
 455         }
 456         return generateConstructor(cl, constructorToCall);
 457     }
 458 
 459     private final Constructor<?> generateConstructor(Class<?> cl,
 460                                                      Constructor<?> constructorToCall) {
 461 
 462 
 463         ConstructorAccessor acc = new MethodAccessorGenerator().
 464             generateSerializationConstructor(cl,
 465                                              constructorToCall.getParameterTypes(),
 466                                              constructorToCall.getExceptionTypes(),
 467                                              constructorToCall.getModifiers(),
 468                                              constructorToCall.getDeclaringClass());
 469         Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(),
 470                                           constructorToCall.getParameterTypes(),
 471                                           constructorToCall.getExceptionTypes(),
 472                                           constructorToCall.getModifiers(),
 473                                           langReflectAccess.
 474                                           getConstructorSlot(constructorToCall),
 475                                           langReflectAccess.
 476                                           getConstructorSignature(constructorToCall),
 477                                           langReflectAccess.
 478                                           getConstructorAnnotations(constructorToCall),
 479                                           langReflectAccess.
 480                                           getConstructorParameterAnnotations(constructorToCall));
 481         setConstructorAccessor(c, acc);
 482         c.setAccessible(true);
 483         return c;
 484     }
 485 
 486     public final MethodHandle readObjectForSerialization(Class<?> cl) {
 487         return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
 488     }
 489 
 490     public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
 491         return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
 492     }
 493 
 494     public final MethodHandle writeObjectForSerialization(Class<?> cl) {
 495         return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
 496     }
 497 
 498     private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
 499                                                                    String methodName,
 500                                                                    Class<?> streamClass) {
 501         if (!Serializable.class.isAssignableFrom(cl)) {
 502             return null;
 503         }
 504 
 505         try {
 506             Method meth = cl.getDeclaredMethod(methodName, streamClass);
 507             int mods = meth.getModifiers();
 508             if (meth.getReturnType() != Void.TYPE ||
 509                     Modifier.isStatic(mods) ||
 510                     !Modifier.isPrivate(mods)) {
 511                 return null;
 512             }
 513             meth.setAccessible(true);
 514             return MethodHandles.lookup().unreflect(meth);
 515         } catch (NoSuchMethodException ex) {
 516             return null;
 517         } catch (IllegalAccessException ex1) {
 518             throw new InternalError("Error", ex1);
 519         }
 520     }
 521 
 522     /**
 523      * Returns a MethodHandle for {@code writeReplace} on the serializable class
 524      * or null if no match found.
 525      * @param cl a serializable class
 526      * @returnss the {@code writeReplace} MethodHandle or {@code null} if not found
 527      */
 528     public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
 529         return getReplaceResolveForSerialization(cl, "writeReplace");
 530     }
 531 
 532     /**
 533      * Returns a MethodHandle for {@code readResolve} on the serializable class
 534      * or null if no match found.
 535      * @param cl a serializable class
 536      * @returns the {@code writeReplace} MethodHandle or {@code null} if not found
 537      */
 538     public final MethodHandle readResolveForSerialization(Class<?> cl) {
 539         return getReplaceResolveForSerialization(cl, "readResolve");
 540     }
 541 
 542     /**
 543      * Lookup readResolve or writeReplace on a class with specified
 544      * signature constraints.
 545      * @param cl a serializable class
 546      * @param methodName the method name to find
 547      * @returns a MethodHandle for the method or {@code null} if not found or
 548      *       has the wrong signature.
 549      */
 550     private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
 551                                                            String methodName) {
 552         if (!Serializable.class.isAssignableFrom(cl)) {
 553             return null;
 554         }
 555 
 556         Class<?> defCl = cl;
 557         while (defCl != null) {
 558             try {
 559                 Method m = defCl.getDeclaredMethod(methodName);
 560                 if (m.getReturnType() != Object.class) {
 561                     return null;
 562                 }
 563                 int mods = m.getModifiers();
 564                 if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
 565                     return null;
 566                 } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
 567                     // fall through
 568                 } else if (Modifier.isPrivate(mods) && (cl != defCl)) {
 569                     return null;
 570                 } else if (!packageEquals(cl, defCl)) {
 571                     return null;
 572                 }
 573                 try {
 574                     // Normal return
 575                     m.setAccessible(true);
 576                     return MethodHandles.lookup().unreflect(m);
 577                 } catch (IllegalAccessException ex0) {
 578                     // setAccessible should prevent IAE
 579                     throw new InternalError("Error", ex0);
 580                 }
 581             } catch (NoSuchMethodException ex) {
 582                 defCl = defCl.getSuperclass();
 583             }
 584         }
 585         return null;
 586     }
 587 
 588     /**
 589      * Returns true if the given class defines a static initializer method,
 590      * false otherwise.
 591      */
 592     public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
 593         Method m = hasStaticInitializerMethod;
 594         if (m == null) {
 595             try {
 596                 m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
 597                         new Class<?>[]{Class.class});
 598                 m.setAccessible(true);
 599                 hasStaticInitializerMethod = m;
 600             } catch (NoSuchMethodException ex) {
 601                 throw new InternalError("No such method hasStaticInitializer on "
 602                         + ObjectStreamClass.class, ex);
 603             }
 604         }
 605         try {
 606             return (Boolean) m.invoke(null, cl);
 607         } catch (InvocationTargetException | IllegalAccessException ex) {
 608             throw new InternalError("Exception invoking hasStaticInitializer", ex);
 609         }
 610     }
 611 
 612     /**
 613      * Return the accessible constructor for OptionalDataException signaling eof.
 614      * @returns the eof constructor for OptionalDataException
 615      */
 616     public final Constructor<OptionalDataException> newOptionalDataExceptionForSerialization() {
 617         try {
 618             Constructor<OptionalDataException> boolCtor =
 619                     OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
 620             boolCtor.setAccessible(true);
 621             return boolCtor;
 622         } catch (NoSuchMethodException ex) {
 623             throw new InternalError("Constructor not found", ex);
 624         }
 625     }
 626 
 627     //--------------------------------------------------------------------------
 628     //
 629     // Internals only below this point
 630     //
 631 
 632     static int inflationThreshold() {
 633         return inflationThreshold;
 634     }
 635 
 636     /** We have to defer full initialization of this class until after
 637         the static initializer is run since java.lang.reflect.Method's
 638         static initializer (more properly, that for
 639         java.lang.reflect.AccessibleObject) causes this class's to be
 640         run, before the system properties are set up. */
 641     private static void checkInitted() {
 642         if (initted) return;
 643 
 644         // Defer initialization until module system is initialized so as
 645         // to avoid inflation and spinning bytecode in unnamed modules
 646         // during early startup.
 647         if (!VM.isModuleSystemInited()) {
 648             return;
 649         }
 650 
 651         Properties props = GetPropertyAction.privilegedGetProperties();
 652         String val = props.getProperty("sun.reflect.noInflation");
 653         if (val != null && val.equals("true")) {
 654             noInflation = true;
 655         }
 656 
 657         val = props.getProperty("sun.reflect.inflationThreshold");
 658         if (val != null) {
 659             try {
 660                 inflationThreshold = Integer.parseInt(val);
 661             } catch (NumberFormatException e) {
 662                 throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
 663             }
 664         }
 665 
 666         disableSerialConstructorChecks =
 667             "true".equals(props.getProperty("jdk.disableSerialConstructorChecks"));
 668 
 669         initted = true;
 670     }
 671 
 672     /**
 673      * Returns true if classes are defined in the classloader and same package, false
 674      * otherwise.
 675      * @param cl1 a class
 676      * @param cl2 another class
 677      * @returns true if the two classes are in the same classloader and package
 678      */
 679     private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
 680         assert !cl1.isArray() && !cl2.isArray();
 681 
 682         if (cl1 == cl2) {
 683             return true;
 684         }
 685 
 686         return cl1.getClassLoader() == cl2.getClassLoader() &&
 687                 Objects.equals(cl1.getPackageName(), cl2.getPackageName());
 688     }
 689 
 690 }