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