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