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