1 /* 2 * Copyright (c) 2001, 2025, 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.ObjectStreamField; 33 import java.io.OptionalDataException; 34 import java.io.Serializable; 35 import java.lang.classfile.ClassFile; 36 import java.lang.invoke.MethodHandle; 37 import java.lang.invoke.MethodHandles; 38 import java.lang.reflect.*; 39 import java.util.Set; 40 41 import jdk.internal.access.JavaLangReflectAccess; 42 import jdk.internal.access.SharedSecrets; 43 import jdk.internal.misc.VM; 44 import jdk.internal.vm.annotation.Stable; 45 46 /** <P> The master factory for all reflective objects, both those in 47 java.lang.reflect (Fields, Methods, Constructors) as well as their 48 delegates (FieldAccessors, MethodAccessors, ConstructorAccessors). 49 </P> 50 51 <P> The methods in this class are extremely unsafe and can cause 52 subversion of both the language and the verifier. For this reason, 53 they are all instance methods, and access to the constructor of 54 this factory is guarded by a security check, in similar style to 55 {@link jdk.internal.misc.Unsafe}. </P> 56 */ 57 58 public class ReflectionFactory { 59 60 private static final ReflectionFactory soleInstance = new ReflectionFactory(); 61 62 63 /* Method for static class initializer <clinit>, or null */ 64 private static volatile Method hasStaticInitializerMethod; 65 66 private final JavaLangReflectAccess langReflectAccess; 67 68 private ReflectionFactory() { 69 this.langReflectAccess = SharedSecrets.getJavaLangReflectAccess(); 70 } 71 72 /** 73 * Provides the caller with the capability to instantiate reflective 74 * objects. 75 * 76 * <p> The returned <code>ReflectionFactory</code> object should be 77 * carefully guarded by the caller, since it can be used to read and 78 * write private data and invoke private methods, as well as to load 79 * unverified bytecodes. It must never be passed to untrusted code. 80 */ 81 public static ReflectionFactory getReflectionFactory() { 82 return soleInstance; 83 } 84 85 //-------------------------------------------------------------------------- 86 // 87 // Routines used by java.lang.reflect 88 // 89 // 90 91 /* 92 * Note: this routine can cause the declaring class for the field 93 * be initialized and therefore must not be called until the 94 * first get/set of this field. 95 * @param field the field 96 * @param override true if caller has overridden accessibility 97 */ 98 public FieldAccessor newFieldAccessor(Field field, boolean override) { 99 Field root = langReflectAccess.getRoot(field); 100 if (root != null) { 101 // FieldAccessor will use the root unless the modifiers have 102 // been overridden 103 if (root.getModifiers() == field.getModifiers() || !override) { 104 field = root; 105 } 106 } 107 boolean isFinal = Modifier.isFinal(field.getModifiers()); 108 boolean isReadOnly = isFinal && (!override || langReflectAccess.isTrustedFinalField(field)); 109 return MethodHandleAccessorFactory.newFieldAccessor(field, isReadOnly); 110 } 111 112 public MethodAccessor newMethodAccessor(Method method, boolean callerSensitive) { 113 // use the root Method that will not cache caller class 114 Method root = langReflectAccess.getRoot(method); 115 if (root != null) { 116 method = root; 117 } 118 119 return MethodHandleAccessorFactory.newMethodAccessor(method, callerSensitive); 120 } 121 122 public ConstructorAccessor newConstructorAccessor(Constructor<?> c) { 123 Class<?> declaringClass = c.getDeclaringClass(); 124 if (Modifier.isAbstract(declaringClass.getModifiers())) { 125 return new InstantiationExceptionConstructorAccessorImpl(null); 126 } 127 if (declaringClass == Class.class) { 128 return new InstantiationExceptionConstructorAccessorImpl 129 ("Can not instantiate java.lang.Class"); 130 } 131 132 // use the root Constructor that will not cache caller class 133 Constructor<?> root = langReflectAccess.getRoot(c); 134 if (root != null) { 135 c = root; 136 } 137 138 return MethodHandleAccessorFactory.newConstructorAccessor(c); 139 } 140 141 //-------------------------------------------------------------------------- 142 // 143 // Routines used by java.lang 144 // 145 // 146 147 /** Makes a copy of the passed method. The returned method is a 148 "child" of the passed one; see the comments in Method.java for 149 details. */ 150 public Method copyMethod(Method arg) { 151 return langReflectAccess.copyMethod(arg); 152 } 153 154 /** Makes a copy of the passed method. The returned method is NOT 155 * a "child" but a "sibling" of the Method in arg. Should only be 156 * used on non-root methods. */ 157 public Method leafCopyMethod(Method arg) { 158 Method root = langReflectAccess.getRoot(arg); 159 return langReflectAccess.copyMethod(root); 160 } 161 162 /** Makes a copy of the passed field. The returned field is a 163 "child" of the passed one; see the comments in Field.java for 164 details. */ 165 public Field copyField(Field arg) { 166 return langReflectAccess.copyField(arg); 167 } 168 169 /** Makes a copy of the passed constructor. The returned 170 constructor is a "child" of the passed one; see the comments 171 in Constructor.java for details. */ 172 public <T> Constructor<T> copyConstructor(Constructor<T> arg) { 173 return langReflectAccess.copyConstructor(arg); 174 } 175 176 /** Gets the byte[] that encodes TypeAnnotations on an executable. 177 */ 178 public byte[] getExecutableTypeAnnotationBytes(Executable ex) { 179 return langReflectAccess.getExecutableTypeAnnotationBytes(ex); 180 } 181 182 public Class<?>[] getExecutableSharedParameterTypes(Executable ex) { 183 return langReflectAccess.getExecutableSharedParameterTypes(ex); 184 } 185 186 public <T> T newInstance(Constructor<T> ctor, Object[] args, Class<?> caller) 187 throws IllegalAccessException, InstantiationException, InvocationTargetException 188 { 189 return langReflectAccess.newInstance(ctor, args, caller); 190 } 191 192 //-------------------------------------------------------------------------- 193 // 194 // Routines used by serialization 195 // 196 // 197 198 public final Constructor<?> newConstructorForExternalization(Class<?> cl) { 199 if (!Externalizable.class.isAssignableFrom(cl)) { 200 return null; 201 } 202 try { 203 Constructor<?> cons = cl.getConstructor(); 204 cons.setAccessible(true); 205 return cons; 206 } catch (NoSuchMethodException ex) { 207 return null; 208 } 209 } 210 211 public final Constructor<?> newConstructorForSerialization(Class<?> cl, 212 Constructor<?> constructorToCall) 213 { 214 if (constructorToCall.getDeclaringClass() == cl) { 215 constructorToCall.setAccessible(true); 216 return constructorToCall; 217 } 218 return generateConstructor(cl, constructorToCall); 219 } 220 221 /** 222 * Given a class, determines whether its superclass has 223 * any constructors that are accessible from the class. 224 * This is a special purpose method intended to do access 225 * checking for a serializable class and its superclasses 226 * up to, but not including, the first non-serializable 227 * superclass. This also implies that the superclass is 228 * always non-null, because a serializable class must be a 229 * class (not an interface) and Object is not serializable. 230 * 231 * @param cl the class from which access is checked 232 * @return whether the superclass has a constructor accessible from cl 233 */ 234 private boolean superHasAccessibleConstructor(Class<?> cl) { 235 Class<?> superCl = cl.getSuperclass(); 236 assert Serializable.class.isAssignableFrom(cl); 237 assert superCl != null; 238 if (packageEquals(cl, superCl)) { 239 // accessible if any non-private constructor is found 240 for (Constructor<?> ctor : superCl.getDeclaredConstructors()) { 241 if ((ctor.getModifiers() & Modifier.PRIVATE) == 0) { 242 return true; 243 } 244 } 245 if (Reflection.areNestMates(cl, superCl)) { 246 return true; 247 } 248 return false; 249 } else { 250 // sanity check to ensure the parent is protected or public 251 if ((superCl.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) { 252 return false; 253 } 254 // accessible if any constructor is protected or public 255 for (Constructor<?> ctor : superCl.getDeclaredConstructors()) { 256 if ((ctor.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0) { 257 return true; 258 } 259 } 260 return false; 261 } 262 } 263 264 /** 265 * Returns a constructor that allocates an instance of cl and that then initializes 266 * the instance by calling the no-arg constructor of its first non-serializable 267 * superclass. This is specified in the Serialization Specification, section 3.1, 268 * in step 11 of the deserialization process. If cl is not serializable, returns 269 * cl's no-arg constructor. If no accessible constructor is found, or if the 270 * class hierarchy is somehow malformed (e.g., a serializable class has no 271 * superclass), null is returned. 272 * 273 * @param cl the class for which a constructor is to be found 274 * @return the generated constructor, or null if none is available 275 */ 276 public final Constructor<?> newConstructorForSerialization(Class<?> cl) { 277 Class<?> initCl = cl; 278 while (Serializable.class.isAssignableFrom(initCl)) { 279 Class<?> prev = initCl; 280 if ((initCl = initCl.getSuperclass()) == null || 281 (!disableSerialConstructorChecks() && !superHasAccessibleConstructor(prev))) { 282 return null; 283 } 284 } 285 Constructor<?> constructorToCall; 286 try { 287 constructorToCall = initCl.getDeclaredConstructor(); 288 int mods = constructorToCall.getModifiers(); 289 if ((mods & Modifier.PRIVATE) != 0 || 290 ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && 291 !packageEquals(cl, initCl))) { 292 return null; 293 } 294 } catch (NoSuchMethodException ex) { 295 return null; 296 } 297 return generateConstructor(cl, constructorToCall); 298 } 299 300 private final Constructor<?> generateConstructor(Class<?> cl, 301 Constructor<?> constructorToCall) { 302 ConstructorAccessor acc = MethodHandleAccessorFactory 303 .newSerializableConstructorAccessor(cl, constructorToCall); 304 // Unlike other root constructors, this constructor is not copied for mutation 305 // but directly mutated, as it is not cached. To cache this constructor, 306 // setAccessible call must be done on a copy and return that copy instead. 307 Constructor<?> ctor = langReflectAccess.newConstructorWithAccessor(constructorToCall, acc); 308 ctor.setAccessible(true); 309 return ctor; 310 } 311 312 public final MethodHandle readObjectForSerialization(Class<?> cl) { 313 return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class); 314 } 315 316 public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) { 317 return findReadWriteObjectForSerialization(cl, "readObjectNoData", null); 318 } 319 320 public final MethodHandle writeObjectForSerialization(Class<?> cl) { 321 return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class); 322 } 323 324 private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl, 325 String methodName, 326 Class<?> streamClass) { 327 if (!Serializable.class.isAssignableFrom(cl)) { 328 return null; 329 } 330 331 try { 332 Method meth = streamClass == null ? cl.getDeclaredMethod(methodName) 333 : cl.getDeclaredMethod(methodName, streamClass); 334 int mods = meth.getModifiers(); 335 if (meth.getReturnType() != Void.TYPE || 336 Modifier.isStatic(mods) || 337 !Modifier.isPrivate(mods)) { 338 return null; 339 } 340 meth.setAccessible(true); 341 return MethodHandles.lookup().unreflect(meth); 342 } catch (NoSuchMethodException ex) { 343 return null; 344 } catch (IllegalAccessException ex1) { 345 throw new InternalError("Error", ex1); 346 } 347 } 348 349 public final MethodHandle defaultReadObjectForSerialization(Class<?> cl) { 350 if (hasDefaultOrNoSerialization(cl)) { 351 return null; 352 } 353 354 return SharedSecrets.getJavaObjectStreamReflectionAccess().defaultReadObject(cl); 355 } 356 357 public final MethodHandle defaultWriteObjectForSerialization(Class<?> cl) { 358 if (hasDefaultOrNoSerialization(cl)) { 359 return null; 360 } 361 362 return SharedSecrets.getJavaObjectStreamReflectionAccess().defaultWriteObject(cl); 363 } 364 365 /** 366 * These are specific leaf classes which appear to be Serializable, but which 367 * have special semantics according to the serialization specification. We 368 * could theoretically include array classes here, but it is easier and clearer 369 * to just use `Class#isArray` instead. 370 */ 371 private static final Set<Class<?>> nonSerializableLeafClasses = Set.of( 372 Class.class, 373 String.class, 374 ObjectStreamClass.class 375 ); 376 377 private static boolean hasDefaultOrNoSerialization(Class<?> cl) { 378 return ! Serializable.class.isAssignableFrom(cl) 379 || cl.isInterface() 380 || cl.isArray() 381 || Proxy.isProxyClass(cl) 382 || Externalizable.class.isAssignableFrom(cl) 383 || cl.isEnum() 384 || cl.isRecord() 385 || cl.isHidden() 386 || nonSerializableLeafClasses.contains(cl); 387 } 388 389 /** 390 * Returns a MethodHandle for {@code writeReplace} on the serializable class 391 * or null if no match found. 392 * @param cl a serializable class 393 * @return the {@code writeReplace} MethodHandle or {@code null} if not found 394 */ 395 public final MethodHandle writeReplaceForSerialization(Class<?> cl) { 396 return getReplaceResolveForSerialization(cl, "writeReplace"); 397 } 398 399 /** 400 * Returns a MethodHandle for {@code readResolve} on the serializable class 401 * or null if no match found. 402 * @param cl a serializable class 403 * @return the {@code writeReplace} MethodHandle or {@code null} if not found 404 */ 405 public final MethodHandle readResolveForSerialization(Class<?> cl) { 406 return getReplaceResolveForSerialization(cl, "readResolve"); 407 } 408 409 /** 410 * Lookup readResolve or writeReplace on a class with specified 411 * signature constraints. 412 * @param cl a serializable class 413 * @param methodName the method name to find 414 * @return a MethodHandle for the method or {@code null} if not found or 415 * has the wrong signature. 416 */ 417 private MethodHandle getReplaceResolveForSerialization(Class<?> cl, 418 String methodName) { 419 if (!Serializable.class.isAssignableFrom(cl)) { 420 return null; 421 } 422 423 Class<?> defCl = cl; 424 while (defCl != null) { 425 try { 426 Method m = defCl.getDeclaredMethod(methodName); 427 if (m.getReturnType() != Object.class) { 428 return null; 429 } 430 int mods = m.getModifiers(); 431 if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) { 432 return null; 433 } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) { 434 // fall through 435 } else if (Modifier.isPrivate(mods) && (cl != defCl)) { 436 return null; 437 } else if (!packageEquals(cl, defCl)) { 438 return null; 439 } 440 try { 441 // Normal return 442 m.setAccessible(true); 443 return MethodHandles.lookup().unreflect(m); 444 } catch (IllegalAccessException ex0) { 445 // setAccessible should prevent IAE 446 throw new InternalError("Error", ex0); 447 } 448 } catch (NoSuchMethodException ex) { 449 defCl = defCl.getSuperclass(); 450 } 451 } 452 return null; 453 } 454 455 /** 456 * Returns true if the given class defines a static initializer method, 457 * false otherwise. 458 */ 459 public final boolean hasStaticInitializerForSerialization(Class<?> cl) { 460 Method m = hasStaticInitializerMethod; 461 if (m == null) { 462 try { 463 m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer", 464 new Class<?>[]{Class.class}); 465 m.setAccessible(true); 466 hasStaticInitializerMethod = m; 467 } catch (NoSuchMethodException ex) { 468 throw new InternalError("No such method hasStaticInitializer on " 469 + ObjectStreamClass.class, ex); 470 } 471 } 472 try { 473 return (Boolean) m.invoke(null, cl); 474 } catch (InvocationTargetException | IllegalAccessException ex) { 475 throw new InternalError("Exception invoking hasStaticInitializer", ex); 476 } 477 } 478 479 /** 480 * Return the accessible constructor for OptionalDataException signaling eof. 481 * @return the eof constructor for OptionalDataException 482 */ 483 public final Constructor<OptionalDataException> newOptionalDataExceptionForSerialization() { 484 try { 485 Constructor<OptionalDataException> boolCtor = 486 OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE); 487 boolCtor.setAccessible(true); 488 return boolCtor; 489 } catch (NoSuchMethodException ex) { 490 throw new InternalError("Constructor not found", ex); 491 } 492 } 493 494 public final ObjectStreamField[] serialPersistentFields(Class<?> cl) { 495 if (! Serializable.class.isAssignableFrom(cl) || cl.isInterface() || cl.isEnum()) { 496 return null; 497 } 498 499 try { 500 Field field = cl.getDeclaredField("serialPersistentFields"); 501 int mods = field.getModifiers(); 502 if (! (Modifier.isStatic(mods) && Modifier.isPrivate(mods) && Modifier.isFinal(mods))) { 503 return null; 504 } 505 if (field.getType() != ObjectStreamField[].class) { 506 return null; 507 } 508 field.setAccessible(true); 509 ObjectStreamField[] array = (ObjectStreamField[]) field.get(null); 510 return array != null && array.length > 0 ? array.clone() : array; 511 } catch (ReflectiveOperationException e) { 512 return null; 513 } 514 } 515 516 public final Set<AccessFlag> parseAccessFlags(int mask, AccessFlag.Location location, Class<?> classFile) { 517 var cffv = classFileFormatVersion(classFile); 518 return cffv == null ? 519 AccessFlag.maskToAccessFlags(mask, location) : 520 AccessFlag.maskToAccessFlags(mask, location, cffv); 521 } 522 523 private final ClassFileFormatVersion classFileFormatVersion(Class<?> cl) { 524 int raw = SharedSecrets.getJavaLangAccess().classFileVersion(cl); 525 526 int major = raw & 0xFFFF; 527 int minor = raw >>> Character.SIZE; 528 529 assert VM.isSupportedClassFileVersion(major, minor) : major + "." + minor; 530 531 if (major >= ClassFile.JAVA_12_VERSION) { 532 if (minor == 0) 533 return ClassFileFormatVersion.fromMajor(raw); 534 return null; // preview or old preview, fallback to default handling 535 } else if (major == ClassFile.JAVA_1_VERSION) { 536 return minor < 3 ? ClassFileFormatVersion.RELEASE_0 : ClassFileFormatVersion.RELEASE_1; 537 } 538 return ClassFileFormatVersion.fromMajor(major); 539 } 540 541 //-------------------------------------------------------------------------- 542 // 543 // Internals only below this point 544 // 545 546 /* 547 * If -Djdk.reflect.useNativeAccessorOnly is set, use the native accessor only. 548 * For testing purpose only. 549 */ 550 static boolean useNativeAccessorOnly() { 551 return config().useNativeAccessorOnly; 552 } 553 554 private static boolean disableSerialConstructorChecks() { 555 return config().disableSerialConstructorChecks; 556 } 557 558 /** 559 * The configuration is lazily initialized after the module system is initialized. The 560 * default config would be used before the proper config is loaded. 561 * 562 * The static initializer of ReflectionFactory is run before the system properties are set up. 563 * The class initialization is caused by the class initialization of java.lang.reflect.Method 564 * (more properly, caused by the class initialization for java.lang.reflect.AccessibleObject) 565 * that happens very early VM startup, initPhase1. 566 */ 567 private static @Stable Config config; 568 569 private static final Config DEFAULT_CONFIG = new Config(false, // useNativeAccessorOnly 570 false); // disableSerialConstructorChecks 571 572 /** 573 * The configurations for the reflection factory. Configurable via 574 * system properties but only available after ReflectionFactory is 575 * loaded during early VM startup. 576 * 577 * Note that the default implementations of the object methods of 578 * this Config record (toString, equals, hashCode) use indy, 579 * which is available to use only after initPhase1. These methods 580 * are currently not called, but should they be needed, a workaround 581 * is to override them. 582 */ 583 private record Config(boolean useNativeAccessorOnly, 584 boolean disableSerialConstructorChecks) { 585 } 586 587 private static Config config() { 588 Config c = config; 589 if (c != null) { 590 return c; 591 } 592 593 // Always use the default configuration until the module system is initialized. 594 if (!VM.isModuleSystemInited()) { 595 return DEFAULT_CONFIG; 596 } 597 598 return config = loadConfig(); 599 } 600 601 private static Config loadConfig() { 602 assert VM.isModuleSystemInited(); 603 604 boolean useNativeAccessorOnly = 605 "true".equals(System.getProperty("jdk.reflect.useNativeAccessorOnly")); 606 boolean disableSerialConstructorChecks = 607 "true".equals(System.getProperty("jdk.disableSerialConstructorChecks")); 608 609 return new Config(useNativeAccessorOnly, disableSerialConstructorChecks); 610 } 611 612 /** 613 * Returns true if classes are defined in the classloader and same package, false 614 * otherwise. 615 * @param cl1 a class 616 * @param cl2 another class 617 * @return true if the two classes are in the same classloader and package 618 */ 619 private static boolean packageEquals(Class<?> cl1, Class<?> cl2) { 620 assert !cl1.isArray() && !cl2.isArray(); 621 622 if (cl1 == cl2) { 623 return true; 624 } 625 626 return cl1.getClassLoader() == cl2.getClassLoader() && 627 cl1.getPackageName() == cl2.getPackageName(); 628 } 629 }