Path: blob/master/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java
41159 views
/*1* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package jdk.internal.reflect;2627import java.io.Externalizable;28import java.io.ObjectInputStream;29import java.io.ObjectOutputStream;30import java.io.ObjectStreamClass;31import java.io.OptionalDataException;32import java.io.Serializable;33import java.lang.invoke.MethodHandle;34import java.lang.invoke.MethodHandles;35import java.lang.reflect.Constructor;36import java.lang.reflect.Executable;37import java.lang.reflect.Field;38import java.lang.reflect.InvocationTargetException;39import java.lang.reflect.Method;40import java.lang.reflect.Modifier;41import java.security.PrivilegedAction;42import java.util.Properties;43import jdk.internal.access.JavaLangReflectAccess;44import jdk.internal.access.SharedSecrets;45import jdk.internal.misc.VM;46import sun.reflect.misc.ReflectUtil;47import sun.security.action.GetPropertyAction;48import sun.security.util.SecurityConstants;4950/** <P> The master factory for all reflective objects, both those in51java.lang.reflect (Fields, Methods, Constructors) as well as their52delegates (FieldAccessors, MethodAccessors, ConstructorAccessors).53</P>5455<P> The methods in this class are extremely unsafe and can cause56subversion of both the language and the verifier. For this reason,57they are all instance methods, and access to the constructor of58this factory is guarded by a security check, in similar style to59{@link jdk.internal.misc.Unsafe}. </P>60*/6162public class ReflectionFactory {6364private static boolean initted = false;65private static final ReflectionFactory soleInstance = new ReflectionFactory();666768/* Method for static class initializer <clinit>, or null */69private static volatile Method hasStaticInitializerMethod;7071//72// "Inflation" mechanism. Loading bytecodes to implement73// Method.invoke() and Constructor.newInstance() currently costs74// 3-4x more than an invocation via native code for the first75// invocation (though subsequent invocations have been benchmarked76// to be over 20x faster). Unfortunately this cost increases77// startup time for certain applications that use reflection78// intensively (but only once per class) to bootstrap themselves.79// To avoid this penalty we reuse the existing JVM entry points80// for the first few invocations of Methods and Constructors and81// then switch to the bytecode-based implementations.82//83// Package-private to be accessible to NativeMethodAccessorImpl84// and NativeConstructorAccessorImpl85private static boolean noInflation = false;86private static int inflationThreshold = 15;8788// true if deserialization constructor checking is disabled89private static boolean disableSerialConstructorChecks = false;9091private final JavaLangReflectAccess langReflectAccess;92private ReflectionFactory() {93this.langReflectAccess = SharedSecrets.getJavaLangReflectAccess();94}9596/**97* A convenience class for acquiring the capability to instantiate98* reflective objects. Use this instead of a raw call to {@link99* #getReflectionFactory} in order to avoid being limited by the100* permissions of your callers.101*102* <p>An instance of this class can be used as the argument of103* <code>AccessController.doPrivileged</code>.104*/105public static final class GetReflectionFactoryAction106implements PrivilegedAction<ReflectionFactory> {107public ReflectionFactory run() {108return getReflectionFactory();109}110}111112/**113* Provides the caller with the capability to instantiate reflective114* objects.115*116* <p> First, if there is a security manager, its117* <code>checkPermission</code> method is called with a {@link118* java.lang.RuntimePermission} with target119* <code>"reflectionFactoryAccess"</code>. This may result in a120* security exception.121*122* <p> The returned <code>ReflectionFactory</code> object should be123* carefully guarded by the caller, since it can be used to read and124* write private data and invoke private methods, as well as to load125* unverified bytecodes. It must never be passed to untrusted code.126*127* @exception SecurityException if a security manager exists and its128* <code>checkPermission</code> method doesn't allow129* access to the RuntimePermission "reflectionFactoryAccess". */130public static ReflectionFactory getReflectionFactory() {131@SuppressWarnings("removal")132SecurityManager security = System.getSecurityManager();133if (security != null) {134security.checkPermission(135SecurityConstants.REFLECTION_FACTORY_ACCESS_PERMISSION);136}137return soleInstance;138}139140/**141* Returns an alternate reflective Method instance for the given method142* intended for reflection to invoke, if present.143*144* A trusted method can define an alternate implementation for a method `foo`145* by defining a method named "reflected$foo" that will be invoked146* reflectively.147*/148private static Method findMethodForReflection(Method method) {149String altName = "reflected$" + method.getName();150try {151return method.getDeclaringClass()152.getDeclaredMethod(altName, method.getParameterTypes());153} catch (NoSuchMethodException ex) {154return null;155}156}157158//--------------------------------------------------------------------------159//160// Routines used by java.lang.reflect161//162//163164/*165* Note: this routine can cause the declaring class for the field166* be initialized and therefore must not be called until the167* first get/set of this field.168* @param field the field169* @param override true if caller has overridden accessibility170*/171public FieldAccessor newFieldAccessor(Field field, boolean override) {172checkInitted();173174Field root = langReflectAccess.getRoot(field);175if (root != null) {176// FieldAccessor will use the root unless the modifiers have177// been overridden178if (root.getModifiers() == field.getModifiers() || !override) {179field = root;180}181}182boolean isFinal = Modifier.isFinal(field.getModifiers());183boolean isReadOnly = isFinal && (!override || langReflectAccess.isTrustedFinalField(field));184return UnsafeFieldAccessorFactory.newFieldAccessor(field, isReadOnly);185}186187public MethodAccessor newMethodAccessor(Method method) {188checkInitted();189190if (Reflection.isCallerSensitive(method)) {191Method altMethod = findMethodForReflection(method);192if (altMethod != null) {193method = altMethod;194}195}196197// use the root Method that will not cache caller class198Method root = langReflectAccess.getRoot(method);199if (root != null) {200method = root;201}202203if (noInflation && !method.getDeclaringClass().isHidden()) {204return new MethodAccessorGenerator().205generateMethod(method.getDeclaringClass(),206method.getName(),207method.getParameterTypes(),208method.getReturnType(),209method.getExceptionTypes(),210method.getModifiers());211} else {212NativeMethodAccessorImpl acc =213new NativeMethodAccessorImpl(method);214DelegatingMethodAccessorImpl res =215new DelegatingMethodAccessorImpl(acc);216acc.setParent(res);217return res;218}219}220221public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {222checkInitted();223224Class<?> declaringClass = c.getDeclaringClass();225if (Modifier.isAbstract(declaringClass.getModifiers())) {226return new InstantiationExceptionConstructorAccessorImpl(null);227}228if (declaringClass == Class.class) {229return new InstantiationExceptionConstructorAccessorImpl230("Can not instantiate java.lang.Class");231}232233// use the root Constructor that will not cache caller class234Constructor<?> root = langReflectAccess.getRoot(c);235if (root != null) {236c = root;237}238239// Bootstrapping issue: since we use Class.newInstance() in240// the ConstructorAccessor generation process, we have to241// break the cycle here.242if (Reflection.isSubclassOf(declaringClass,243ConstructorAccessorImpl.class)) {244return new BootstrapConstructorAccessorImpl(c);245}246247if (noInflation && !c.getDeclaringClass().isHidden()) {248return new MethodAccessorGenerator().249generateConstructor(c.getDeclaringClass(),250c.getParameterTypes(),251c.getExceptionTypes(),252c.getModifiers());253} else {254NativeConstructorAccessorImpl acc =255new NativeConstructorAccessorImpl(c);256DelegatingConstructorAccessorImpl res =257new DelegatingConstructorAccessorImpl(acc);258acc.setParent(res);259return res;260}261}262263//--------------------------------------------------------------------------264//265// Routines used by java.lang266//267//268269/** Creates a new java.lang.reflect.Constructor. Access checks as270per java.lang.reflect.AccessibleObject are not overridden. */271public Constructor<?> newConstructor(Class<?> declaringClass,272Class<?>[] parameterTypes,273Class<?>[] checkedExceptions,274int modifiers,275int slot,276String signature,277byte[] annotations,278byte[] parameterAnnotations)279{280return langReflectAccess.newConstructor(declaringClass,281parameterTypes,282checkedExceptions,283modifiers,284slot,285signature,286annotations,287parameterAnnotations);288}289290/** Gets the ConstructorAccessor object for a291java.lang.reflect.Constructor */292public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {293return langReflectAccess.getConstructorAccessor(c);294}295296/** Sets the ConstructorAccessor object for a297java.lang.reflect.Constructor */298public void setConstructorAccessor(Constructor<?> c,299ConstructorAccessor accessor)300{301langReflectAccess.setConstructorAccessor(c, accessor);302}303304/** Makes a copy of the passed method. The returned method is a305"child" of the passed one; see the comments in Method.java for306details. */307public Method copyMethod(Method arg) {308return langReflectAccess.copyMethod(arg);309}310311/** Makes a copy of the passed method. The returned method is NOT312* a "child" but a "sibling" of the Method in arg. Should only be313* used on non-root methods. */314public Method leafCopyMethod(Method arg) {315return langReflectAccess.leafCopyMethod(arg);316}317318319/** Makes a copy of the passed field. The returned field is a320"child" of the passed one; see the comments in Field.java for321details. */322public Field copyField(Field arg) {323return langReflectAccess.copyField(arg);324}325326/** Makes a copy of the passed constructor. The returned327constructor is a "child" of the passed one; see the comments328in Constructor.java for details. */329public <T> Constructor<T> copyConstructor(Constructor<T> arg) {330return langReflectAccess.copyConstructor(arg);331}332333/** Gets the byte[] that encodes TypeAnnotations on an executable.334*/335public byte[] getExecutableTypeAnnotationBytes(Executable ex) {336return langReflectAccess.getExecutableTypeAnnotationBytes(ex);337}338339public Class<?>[] getExecutableSharedParameterTypes(Executable ex) {340return langReflectAccess.getExecutableSharedParameterTypes(ex);341}342343public <T> T newInstance(Constructor<T> ctor, Object[] args, Class<?> caller)344throws IllegalAccessException, InstantiationException, InvocationTargetException345{346return langReflectAccess.newInstance(ctor, args, caller);347}348349//--------------------------------------------------------------------------350//351// Routines used by serialization352//353//354355public final Constructor<?> newConstructorForExternalization(Class<?> cl) {356if (!Externalizable.class.isAssignableFrom(cl)) {357return null;358}359try {360Constructor<?> cons = cl.getConstructor();361cons.setAccessible(true);362return cons;363} catch (NoSuchMethodException ex) {364return null;365}366}367368public final Constructor<?> newConstructorForSerialization(Class<?> cl,369Constructor<?> constructorToCall)370{371if (constructorToCall.getDeclaringClass() == cl) {372constructorToCall.setAccessible(true);373return constructorToCall;374}375return generateConstructor(cl, constructorToCall);376}377378/**379* Given a class, determines whether its superclass has380* any constructors that are accessible from the class.381* This is a special purpose method intended to do access382* checking for a serializable class and its superclasses383* up to, but not including, the first non-serializable384* superclass. This also implies that the superclass is385* always non-null, because a serializable class must be a386* class (not an interface) and Object is not serializable.387*388* @param cl the class from which access is checked389* @return whether the superclass has a constructor accessible from cl390*/391private boolean superHasAccessibleConstructor(Class<?> cl) {392Class<?> superCl = cl.getSuperclass();393assert Serializable.class.isAssignableFrom(cl);394assert superCl != null;395if (packageEquals(cl, superCl)) {396// accessible if any non-private constructor is found397for (Constructor<?> ctor : superCl.getDeclaredConstructors()) {398if ((ctor.getModifiers() & Modifier.PRIVATE) == 0) {399return true;400}401}402if (Reflection.areNestMates(cl, superCl)) {403return true;404}405return false;406} else {407// sanity check to ensure the parent is protected or public408if ((superCl.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) {409return false;410}411// accessible if any constructor is protected or public412for (Constructor<?> ctor : superCl.getDeclaredConstructors()) {413if ((ctor.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0) {414return true;415}416}417return false;418}419}420421/**422* Returns a constructor that allocates an instance of cl and that then initializes423* the instance by calling the no-arg constructor of its first non-serializable424* superclass. This is specified in the Serialization Specification, section 3.1,425* in step 11 of the deserialization process. If cl is not serializable, returns426* cl's no-arg constructor. If no accessible constructor is found, or if the427* class hierarchy is somehow malformed (e.g., a serializable class has no428* superclass), null is returned.429*430* @param cl the class for which a constructor is to be found431* @return the generated constructor, or null if none is available432*/433public final Constructor<?> newConstructorForSerialization(Class<?> cl) {434Class<?> initCl = cl;435while (Serializable.class.isAssignableFrom(initCl)) {436Class<?> prev = initCl;437if ((initCl = initCl.getSuperclass()) == null ||438(!disableSerialConstructorChecks && !superHasAccessibleConstructor(prev))) {439return null;440}441}442Constructor<?> constructorToCall;443try {444constructorToCall = initCl.getDeclaredConstructor();445int mods = constructorToCall.getModifiers();446if ((mods & Modifier.PRIVATE) != 0 ||447((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&448!packageEquals(cl, initCl))) {449return null;450}451} catch (NoSuchMethodException ex) {452return null;453}454return generateConstructor(cl, constructorToCall);455}456457private final Constructor<?> generateConstructor(Class<?> cl,458Constructor<?> constructorToCall) {459460461ConstructorAccessor acc = new MethodAccessorGenerator().462generateSerializationConstructor(cl,463constructorToCall.getParameterTypes(),464constructorToCall.getExceptionTypes(),465constructorToCall.getModifiers(),466constructorToCall.getDeclaringClass());467Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(),468constructorToCall.getParameterTypes(),469constructorToCall.getExceptionTypes(),470constructorToCall.getModifiers(),471langReflectAccess.472getConstructorSlot(constructorToCall),473langReflectAccess.474getConstructorSignature(constructorToCall),475langReflectAccess.476getConstructorAnnotations(constructorToCall),477langReflectAccess.478getConstructorParameterAnnotations(constructorToCall));479setConstructorAccessor(c, acc);480c.setAccessible(true);481return c;482}483484public final MethodHandle readObjectForSerialization(Class<?> cl) {485return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);486}487488public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {489return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);490}491492public final MethodHandle writeObjectForSerialization(Class<?> cl) {493return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);494}495496private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,497String methodName,498Class<?> streamClass) {499if (!Serializable.class.isAssignableFrom(cl)) {500return null;501}502503try {504Method meth = cl.getDeclaredMethod(methodName, streamClass);505int mods = meth.getModifiers();506if (meth.getReturnType() != Void.TYPE ||507Modifier.isStatic(mods) ||508!Modifier.isPrivate(mods)) {509return null;510}511meth.setAccessible(true);512return MethodHandles.lookup().unreflect(meth);513} catch (NoSuchMethodException ex) {514return null;515} catch (IllegalAccessException ex1) {516throw new InternalError("Error", ex1);517}518}519520/**521* Returns a MethodHandle for {@code writeReplace} on the serializable class522* or null if no match found.523* @param cl a serializable class524* @returnss the {@code writeReplace} MethodHandle or {@code null} if not found525*/526public final MethodHandle writeReplaceForSerialization(Class<?> cl) {527return getReplaceResolveForSerialization(cl, "writeReplace");528}529530/**531* Returns a MethodHandle for {@code readResolve} on the serializable class532* or null if no match found.533* @param cl a serializable class534* @returns the {@code writeReplace} MethodHandle or {@code null} if not found535*/536public final MethodHandle readResolveForSerialization(Class<?> cl) {537return getReplaceResolveForSerialization(cl, "readResolve");538}539540/**541* Lookup readResolve or writeReplace on a class with specified542* signature constraints.543* @param cl a serializable class544* @param methodName the method name to find545* @returns a MethodHandle for the method or {@code null} if not found or546* has the wrong signature.547*/548private MethodHandle getReplaceResolveForSerialization(Class<?> cl,549String methodName) {550if (!Serializable.class.isAssignableFrom(cl)) {551return null;552}553554Class<?> defCl = cl;555while (defCl != null) {556try {557Method m = defCl.getDeclaredMethod(methodName);558if (m.getReturnType() != Object.class) {559return null;560}561int mods = m.getModifiers();562if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {563return null;564} else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {565// fall through566} else if (Modifier.isPrivate(mods) && (cl != defCl)) {567return null;568} else if (!packageEquals(cl, defCl)) {569return null;570}571try {572// Normal return573m.setAccessible(true);574return MethodHandles.lookup().unreflect(m);575} catch (IllegalAccessException ex0) {576// setAccessible should prevent IAE577throw new InternalError("Error", ex0);578}579} catch (NoSuchMethodException ex) {580defCl = defCl.getSuperclass();581}582}583return null;584}585586/**587* Returns true if the given class defines a static initializer method,588* false otherwise.589*/590public final boolean hasStaticInitializerForSerialization(Class<?> cl) {591Method m = hasStaticInitializerMethod;592if (m == null) {593try {594m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",595new Class<?>[]{Class.class});596m.setAccessible(true);597hasStaticInitializerMethod = m;598} catch (NoSuchMethodException ex) {599throw new InternalError("No such method hasStaticInitializer on "600+ ObjectStreamClass.class, ex);601}602}603try {604return (Boolean) m.invoke(null, cl);605} catch (InvocationTargetException | IllegalAccessException ex) {606throw new InternalError("Exception invoking hasStaticInitializer", ex);607}608}609610/**611* Return the accessible constructor for OptionalDataException signaling eof.612* @returns the eof constructor for OptionalDataException613*/614public final Constructor<OptionalDataException> newOptionalDataExceptionForSerialization() {615try {616Constructor<OptionalDataException> boolCtor =617OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);618boolCtor.setAccessible(true);619return boolCtor;620} catch (NoSuchMethodException ex) {621throw new InternalError("Constructor not found", ex);622}623}624625//--------------------------------------------------------------------------626//627// Internals only below this point628//629630static int inflationThreshold() {631return inflationThreshold;632}633634/** We have to defer full initialization of this class until after635the static initializer is run since java.lang.reflect.Method's636static initializer (more properly, that for637java.lang.reflect.AccessibleObject) causes this class's to be638run, before the system properties are set up. */639private static void checkInitted() {640if (initted) return;641642// Defer initialization until module system is initialized so as643// to avoid inflation and spinning bytecode in unnamed modules644// during early startup.645if (!VM.isModuleSystemInited()) {646return;647}648649Properties props = GetPropertyAction.privilegedGetProperties();650String val = props.getProperty("sun.reflect.noInflation");651if (val != null && val.equals("true")) {652noInflation = true;653}654655val = props.getProperty("sun.reflect.inflationThreshold");656if (val != null) {657try {658inflationThreshold = Integer.parseInt(val);659} catch (NumberFormatException e) {660throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);661}662}663664disableSerialConstructorChecks =665"true".equals(props.getProperty("jdk.disableSerialConstructorChecks"));666667initted = true;668}669670/**671* Returns true if classes are defined in the classloader and same package, false672* otherwise.673* @param cl1 a class674* @param cl2 another class675* @returns true if the two classes are in the same classloader and package676*/677private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {678assert !cl1.isArray() && !cl2.isArray();679680if (cl1 == cl2) {681return true;682}683684return cl1.getClassLoader() == cl2.getClassLoader() &&685cl1.getPackageName() == cl2.getPackageName();686}687688}689690691