< prev index next >

src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java

Print this page

  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 */

 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

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;

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);

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.

  1 /*
  2  * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.internal.reflect;
 27 
 28 import java.io.Externalizable;
 29 import java.io.ObjectInputStream;
 30 import java.io.ObjectOutputStream;
 31 import java.io.ObjectStreamClass;
 32 import java.io.ObjectStreamField;
 33 import java.io.OptionalDataException;
 34 import java.io.Serializable;

 35 import java.lang.invoke.MethodHandle;
 36 import java.lang.invoke.MethodHandles;
 37 import java.lang.reflect.*;
 38 import java.util.Set;
 39 
 40 import jdk.internal.access.JavaLangReflectAccess;
 41 import jdk.internal.access.SharedSecrets;
 42 import jdk.internal.misc.VM;
 43 import jdk.internal.value.ValueClass;
 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 */

 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) || field.isStrictInit());
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

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         if (cl.isValue()) {
203             throw new UnsupportedOperationException("newConstructorForExternalization does not support value classes");
204         }
205         try {
206             Constructor<?> cons = cl.getConstructor();
207             cons.setAccessible(true);
208             return cons;
209         } catch (NoSuchMethodException ex) {
210             return null;
211         }
212     }
213 
214     public final Constructor<?> newConstructorForSerialization(Class<?> cl,
215                                                                Constructor<?> constructorToCall)
216     {
217         if (constructorToCall.getDeclaringClass() == cl) {
218             constructorToCall.setAccessible(true);
219             return constructorToCall;
220         }
221 
222         return generateConstructor(cl, constructorToCall);
223     }
224 
225     /**
226      * Given a class, determines whether its superclass has
227      * any constructors that are accessible from the class.
228      * This is a special purpose method intended to do access
229      * checking for a serializable class and its superclasses
230      * up to, but not including, the first non-serializable
231      * superclass. This also implies that the superclass is
232      * always non-null, because a serializable class must be a
233      * class (not an interface) and Object is not serializable.
234      *
235      * @param cl the class from which access is checked
236      * @return whether the superclass has a constructor accessible from cl
237      */
238     private boolean superHasAccessibleConstructor(Class<?> cl) {
239         Class<?> superCl = cl.getSuperclass();
240         assert Serializable.class.isAssignableFrom(cl);
241         assert superCl != null;

255             if ((superCl.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) {
256                 return false;
257             }
258             // accessible if any constructor is protected or public
259             for (Constructor<?> ctor : superCl.getDeclaredConstructors()) {
260                 if ((ctor.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0) {
261                     return true;
262                 }
263             }
264             return false;
265         }
266     }
267 
268     /**
269      * Returns a constructor that allocates an instance of cl and that then initializes
270      * the instance by calling the no-arg constructor of its first non-serializable
271      * superclass. This is specified in the Serialization Specification, section 3.1,
272      * in step 11 of the deserialization process. If cl is not serializable, returns
273      * cl's no-arg constructor. If no accessible constructor is found, or if the
274      * class hierarchy is somehow malformed (e.g., a serializable class has no
275      * superclass), or if this serializable class or a serializable superclass
276      * declares a strictly-initialized non-static field, null is returned.
277      *
278      * @param cl the class for which a constructor is to be found
279      * @return the generated constructor, or null if none is available
280      */
281     public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
282         if (cl.isValue()) {
283             return null;
284         }
285 
286         Class<?> initCl = cl;
287         while (Serializable.class.isAssignableFrom(initCl)) {
288             Class<?> prev = initCl;
289             if ((initCl = initCl.getSuperclass()) == null || ValueClass.hasStrictInstanceField(prev) ||
290                 (!disableSerialConstructorChecks() && !superHasAccessibleConstructor(prev))) {
291                 return null;
292             }
293         }
294         Constructor<?> constructorToCall;
295         try {
296             constructorToCall = initCl.getDeclaredConstructor();
297             int mods = constructorToCall.getModifiers();
298             if ((mods & Modifier.PRIVATE) != 0 ||
299                     ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
300                             !packageEquals(cl, initCl))) {
301                 return null;
302             }
303         } catch (NoSuchMethodException ex) {
304             return null;
305         }
306 
307         return newConstructorForSerialization(cl, constructorToCall);
308     }
309 
310     private final Constructor<?> generateConstructor(Class<?> cl,
311                                                      Constructor<?> constructorToCall) {
312         ConstructorAccessor acc = MethodHandleAccessorFactory
313                 .newSerializableConstructorAccessor(cl, constructorToCall);
314         // Unlike other root constructors, this constructor is not copied for mutation
315         // but directly mutated, as it is not cached. To cache this constructor,
316         // setAccessible call must be done on a copy and return that copy instead.
317         Constructor<?> ctor = langReflectAccess.newConstructorWithAccessor(constructorToCall, acc);
318         ctor.setAccessible(true);
319         return ctor;
320     }
321 
322     public final MethodHandle readObjectForSerialization(Class<?> cl) {
323         return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
324     }
325 
326     public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
327         return findReadWriteObjectForSerialization(cl, "readObjectNoData", null);

506             return null;
507         }
508 
509         try {
510             Field field = cl.getDeclaredField("serialPersistentFields");
511             int mods = field.getModifiers();
512             if (! (Modifier.isStatic(mods) && Modifier.isPrivate(mods) && Modifier.isFinal(mods))) {
513                 return null;
514             }
515             if (field.getType() != ObjectStreamField[].class) {
516                 return null;
517             }
518             field.setAccessible(true);
519             ObjectStreamField[] array = (ObjectStreamField[]) field.get(null);
520             return array != null && array.length > 0 ? array.clone() : array;
521         } catch (ReflectiveOperationException e) {
522             return null;
523         }
524     }
525 

























526     //--------------------------------------------------------------------------
527     //
528     // Internals only below this point
529     //
530 
531     /*
532      * If -Djdk.reflect.useNativeAccessorOnly is set, use the native accessor only.
533      * For testing purpose only.
534      */
535     static boolean useNativeAccessorOnly() {
536         return config().useNativeAccessorOnly;
537     }
538 
539     private static boolean disableSerialConstructorChecks() {
540         return config().disableSerialConstructorChecks;
541     }
542 
543     /**
544      * The configuration is lazily initialized after the module system is initialized. The
545      * default config would be used before the proper config is loaded.
< prev index next >