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 if (cl.isValue()) { 203 throw new UnsupportedOperationException("newConstructorForExternalization does not support value classes"); 204 } 205 try { 206 Constructor<?> cons = cl.getConstructor(); 207 cons.setAccessible(true); 208 return cons; 209 } catch (NoSuchMethodException ex) { 210 return null; 211 } 212 } 213 214 public final Constructor<?> newConstructorForSerialization(Class<?> cl, 215 Constructor<?> constructorToCall) 216 { 217 if (constructorToCall.getDeclaringClass() == cl) { 218 constructorToCall.setAccessible(true); 219 return constructorToCall; 220 } 221 if (cl.isValue()) { 222 throw new UnsupportedOperationException("newConstructorForSerialization does not support value classes"); 223 } 224 return generateConstructor(cl, constructorToCall); 225 } 226 227 /** 228 * Given a class, determines whether its superclass has 229 * any constructors that are accessible from the class. 230 * This is a special purpose method intended to do access 231 * checking for a serializable class and its superclasses 232 * up to, but not including, the first non-serializable 233 * superclass. This also implies that the superclass is 234 * always non-null, because a serializable class must be a 235 * class (not an interface) and Object is not serializable. 236 * 237 * @param cl the class from which access is checked 238 * @return whether the superclass has a constructor accessible from cl 239 */ 240 private boolean superHasAccessibleConstructor(Class<?> cl) { 241 Class<?> superCl = cl.getSuperclass(); 242 assert Serializable.class.isAssignableFrom(cl); 243 assert superCl != null; 244 if (packageEquals(cl, superCl)) { 245 // accessible if any non-private constructor is found 246 for (Constructor<?> ctor : superCl.getDeclaredConstructors()) { 247 if ((ctor.getModifiers() & Modifier.PRIVATE) == 0) { 248 return true; 249 } 250 } 251 if (Reflection.areNestMates(cl, superCl)) { 252 return true; 253 } 254 return false; 255 } else { 256 // sanity check to ensure the parent is protected or public 257 if ((superCl.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) { 258 return false; 259 } 260 // accessible if any constructor is protected or public 261 for (Constructor<?> ctor : superCl.getDeclaredConstructors()) { 262 if ((ctor.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0) { 263 return true; 264 } 265 } 266 return false; 267 } 268 } 269 270 /** 271 * Returns a constructor that allocates an instance of cl and that then initializes 272 * the instance by calling the no-arg constructor of its first non-serializable 273 * superclass. This is specified in the Serialization Specification, section 3.1, 274 * in step 11 of the deserialization process. If cl is not serializable, returns 275 * cl's no-arg constructor. If no accessible constructor is found, or if the 276 * class hierarchy is somehow malformed (e.g., a serializable class has no 277 * superclass), null is returned. 278 * 279 * @param cl the class for which a constructor is to be found 280 * @return the generated constructor, or null if none is available 281 */ 282 public final Constructor<?> newConstructorForSerialization(Class<?> cl) { 283 if (cl.isValue()) { 284 throw new UnsupportedOperationException("newConstructorForSerialization does not support value classes: " + cl); 285 } 286 287 Class<?> initCl = cl; 288 while (Serializable.class.isAssignableFrom(initCl)) { 289 Class<?> prev = initCl; 290 if ((initCl = initCl.getSuperclass()) == null || 291 (!disableSerialConstructorChecks() && !superHasAccessibleConstructor(prev))) { 292 return null; 293 } 294 } 295 Constructor<?> constructorToCall; 296 try { 297 constructorToCall = initCl.getDeclaredConstructor(); 298 int mods = constructorToCall.getModifiers(); 299 if ((mods & Modifier.PRIVATE) != 0 || 300 ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && 301 !packageEquals(cl, initCl))) { 302 return null; 303 } 304 } catch (NoSuchMethodException ex) { 305 return null; 306 } 307 return generateConstructor(cl, constructorToCall); 308 } 309 310 private final Constructor<?> generateConstructor(Class<?> cl, 311 Constructor<?> constructorToCall) { 312 ConstructorAccessor acc = MethodHandleAccessorFactory 313 .newSerializableConstructorAccessor(cl, constructorToCall); 314 // Unlike other root constructors, this constructor is not copied for mutation 315 // but directly mutated, as it is not cached. To cache this constructor, 316 // setAccessible call must be done on a copy and return that copy instead. 317 Constructor<?> ctor = langReflectAccess.newConstructorWithAccessor(constructorToCall, acc); 318 ctor.setAccessible(true); 319 return ctor; 320 } 321 322 public final MethodHandle readObjectForSerialization(Class<?> cl) { 323 return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class); 324 } 325 326 public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) { 327 return findReadWriteObjectForSerialization(cl, "readObjectNoData", null); 328 } 329 330 public final MethodHandle writeObjectForSerialization(Class<?> cl) { 331 return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class); 332 } 333 334 private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl, 335 String methodName, 336 Class<?> streamClass) { 337 if (!Serializable.class.isAssignableFrom(cl)) { 338 return null; 339 } 340 341 try { 342 Method meth = streamClass == null ? cl.getDeclaredMethod(methodName) 343 : cl.getDeclaredMethod(methodName, streamClass); 344 int mods = meth.getModifiers(); 345 if (meth.getReturnType() != Void.TYPE || 346 Modifier.isStatic(mods) || 347 !Modifier.isPrivate(mods)) { 348 return null; 349 } 350 meth.setAccessible(true); 351 return MethodHandles.lookup().unreflect(meth); 352 } catch (NoSuchMethodException ex) { 353 return null; 354 } catch (IllegalAccessException ex1) { 355 throw new InternalError("Error", ex1); 356 } 357 } 358 359 public final MethodHandle defaultReadObjectForSerialization(Class<?> cl) { 360 if (hasDefaultOrNoSerialization(cl)) { 361 return null; 362 } 363 364 return SharedSecrets.getJavaObjectStreamReflectionAccess().defaultReadObject(cl); 365 } 366 367 public final MethodHandle defaultWriteObjectForSerialization(Class<?> cl) { 368 if (hasDefaultOrNoSerialization(cl)) { 369 return null; 370 } 371 372 return SharedSecrets.getJavaObjectStreamReflectionAccess().defaultWriteObject(cl); 373 } 374 375 /** 376 * These are specific leaf classes which appear to be Serializable, but which 377 * have special semantics according to the serialization specification. We 378 * could theoretically include array classes here, but it is easier and clearer 379 * to just use `Class#isArray` instead. 380 */ 381 private static final Set<Class<?>> nonSerializableLeafClasses = Set.of( 382 Class.class, 383 String.class, 384 ObjectStreamClass.class 385 ); 386 387 private static boolean hasDefaultOrNoSerialization(Class<?> cl) { 388 return ! Serializable.class.isAssignableFrom(cl) 389 || cl.isInterface() 390 || cl.isArray() 391 || Proxy.isProxyClass(cl) 392 || Externalizable.class.isAssignableFrom(cl) 393 || cl.isEnum() 394 || cl.isRecord() 395 || cl.isHidden() 396 || nonSerializableLeafClasses.contains(cl); 397 } 398 399 /** 400 * Returns a MethodHandle for {@code writeReplace} 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 writeReplaceForSerialization(Class<?> cl) { 406 return getReplaceResolveForSerialization(cl, "writeReplace"); 407 } 408 409 /** 410 * Returns a MethodHandle for {@code readResolve} on the serializable class 411 * or null if no match found. 412 * @param cl a serializable class 413 * @return the {@code writeReplace} MethodHandle or {@code null} if not found 414 */ 415 public final MethodHandle readResolveForSerialization(Class<?> cl) { 416 return getReplaceResolveForSerialization(cl, "readResolve"); 417 } 418 419 /** 420 * Lookup readResolve or writeReplace on a class with specified 421 * signature constraints. 422 * @param cl a serializable class 423 * @param methodName the method name to find 424 * @return a MethodHandle for the method or {@code null} if not found or 425 * has the wrong signature. 426 */ 427 private MethodHandle getReplaceResolveForSerialization(Class<?> cl, 428 String methodName) { 429 if (!Serializable.class.isAssignableFrom(cl)) { 430 return null; 431 } 432 433 Class<?> defCl = cl; 434 while (defCl != null) { 435 try { 436 Method m = defCl.getDeclaredMethod(methodName); 437 if (m.getReturnType() != Object.class) { 438 return null; 439 } 440 int mods = m.getModifiers(); 441 if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) { 442 return null; 443 } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) { 444 // fall through 445 } else if (Modifier.isPrivate(mods) && (cl != defCl)) { 446 return null; 447 } else if (!packageEquals(cl, defCl)) { 448 return null; 449 } 450 try { 451 // Normal return 452 m.setAccessible(true); 453 return MethodHandles.lookup().unreflect(m); 454 } catch (IllegalAccessException ex0) { 455 // setAccessible should prevent IAE 456 throw new InternalError("Error", ex0); 457 } 458 } catch (NoSuchMethodException ex) { 459 defCl = defCl.getSuperclass(); 460 } 461 } 462 return null; 463 } 464 465 /** 466 * Returns true if the given class defines a static initializer method, 467 * false otherwise. 468 */ 469 public final boolean hasStaticInitializerForSerialization(Class<?> cl) { 470 Method m = hasStaticInitializerMethod; 471 if (m == null) { 472 try { 473 m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer", 474 new Class<?>[]{Class.class}); 475 m.setAccessible(true); 476 hasStaticInitializerMethod = m; 477 } catch (NoSuchMethodException ex) { 478 throw new InternalError("No such method hasStaticInitializer on " 479 + ObjectStreamClass.class, ex); 480 } 481 } 482 try { 483 return (Boolean) m.invoke(null, cl); 484 } catch (InvocationTargetException | IllegalAccessException ex) { 485 throw new InternalError("Exception invoking hasStaticInitializer", ex); 486 } 487 } 488 489 /** 490 * Return the accessible constructor for OptionalDataException signaling eof. 491 * @return the eof constructor for OptionalDataException 492 */ 493 public final Constructor<OptionalDataException> newOptionalDataExceptionForSerialization() { 494 try { 495 Constructor<OptionalDataException> boolCtor = 496 OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE); 497 boolCtor.setAccessible(true); 498 return boolCtor; 499 } catch (NoSuchMethodException ex) { 500 throw new InternalError("Constructor not found", ex); 501 } 502 } 503 504 public final ObjectStreamField[] serialPersistentFields(Class<?> cl) { 505 if (! Serializable.class.isAssignableFrom(cl) || cl.isInterface() || cl.isEnum()) { 506 return null; 507 } 508 509 try { 510 Field field = cl.getDeclaredField("serialPersistentFields"); 511 int mods = field.getModifiers(); 512 if (! (Modifier.isStatic(mods) && Modifier.isPrivate(mods) && Modifier.isFinal(mods))) { 513 return null; 514 } 515 if (field.getType() != ObjectStreamField[].class) { 516 return null; 517 } 518 field.setAccessible(true); 519 ObjectStreamField[] array = (ObjectStreamField[]) field.get(null); 520 return array != null && array.length > 0 ? array.clone() : array; 521 } catch (ReflectiveOperationException e) { 522 return null; 523 } 524 } 525 526 public final Set<AccessFlag> parseAccessFlags(int mask, AccessFlag.Location location, Class<?> classFile) { 527 return AccessFlag.maskToAccessFlags(mask, location, classFileFormatVersion(classFile)); 528 } 529 530 public final ClassFileFormatVersion classFileFormatVersion(Class<?> cl) { 531 if (cl.isArray() || cl.isPrimitive()) 532 return ClassFileFormatVersion.CURRENT_PREVIEW_FEATURES; 533 int raw = SharedSecrets.getJavaLangAccess().classFileVersion(cl); 534 535 int major = raw & 0xFFFF; 536 int minor = raw >>> Character.SIZE; 537 538 assert VM.isSupportedClassFileVersion(major, minor) : major + "." + minor; 539 540 if (major >= ClassFile.JAVA_12_VERSION) { 541 if (minor == 0) 542 return ClassFileFormatVersion.fromMajor(raw); 543 return ClassFileFormatVersion.CURRENT_PREVIEW_FEATURES; 544 } else if (major == ClassFile.JAVA_1_VERSION) { 545 return minor < 3 ? ClassFileFormatVersion.RELEASE_0 : ClassFileFormatVersion.RELEASE_1; 546 } 547 return ClassFileFormatVersion.fromMajor(major); 548 } 549 550 //-------------------------------------------------------------------------- 551 // 552 // Internals only below this point 553 // 554 555 /* 556 * If -Djdk.reflect.useNativeAccessorOnly is set, use the native accessor only. 557 * For testing purpose only. 558 */ 559 static boolean useNativeAccessorOnly() { 560 return config().useNativeAccessorOnly; 561 } 562 563 private static boolean disableSerialConstructorChecks() { 564 return config().disableSerialConstructorChecks; 565 } 566 567 /** 568 * The configuration is lazily initialized after the module system is initialized. The 569 * default config would be used before the proper config is loaded. 570 * 571 * The static initializer of ReflectionFactory is run before the system properties are set up. 572 * The class initialization is caused by the class initialization of java.lang.reflect.Method 573 * (more properly, caused by the class initialization for java.lang.reflect.AccessibleObject) 574 * that happens very early VM startup, initPhase1. 575 */ 576 private static @Stable Config config; 577 578 private static final Config DEFAULT_CONFIG = new Config(false, // useNativeAccessorOnly 579 false); // disableSerialConstructorChecks 580 581 /** 582 * The configurations for the reflection factory. Configurable via 583 * system properties but only available after ReflectionFactory is 584 * loaded during early VM startup. 585 * 586 * Note that the default implementations of the object methods of 587 * this Config record (toString, equals, hashCode) use indy, 588 * which is available to use only after initPhase1. These methods 589 * are currently not called, but should they be needed, a workaround 590 * is to override them. 591 */ 592 private record Config(boolean useNativeAccessorOnly, 593 boolean disableSerialConstructorChecks) { 594 } 595 596 private static Config config() { 597 Config c = config; 598 if (c != null) { 599 return c; 600 } 601 602 // Always use the default configuration until the module system is initialized. 603 if (!VM.isModuleSystemInited()) { 604 return DEFAULT_CONFIG; 605 } 606 607 return config = loadConfig(); 608 } 609 610 private static Config loadConfig() { 611 assert VM.isModuleSystemInited(); 612 613 boolean useNativeAccessorOnly = 614 "true".equals(System.getProperty("jdk.reflect.useNativeAccessorOnly")); 615 boolean disableSerialConstructorChecks = 616 "true".equals(System.getProperty("jdk.disableSerialConstructorChecks")); 617 618 return new Config(useNativeAccessorOnly, disableSerialConstructorChecks); 619 } 620 621 /** 622 * Returns true if classes are defined in the classloader and same package, false 623 * otherwise. 624 * @param cl1 a class 625 * @param cl2 another class 626 * @return true if the two classes are in the same classloader and package 627 */ 628 private static boolean packageEquals(Class<?> cl1, Class<?> cl2) { 629 assert !cl1.isArray() && !cl2.isArray(); 630 631 if (cl1 == cl2) { 632 return true; 633 } 634 635 return cl1.getClassLoader() == cl2.getClassLoader() && 636 cl1.getPackageName() == cl2.getPackageName(); 637 } 638 }