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