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