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