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