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