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