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