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