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