Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/reflect/ReflectionFactory.java
38829 views
/*1* Copyright (c) 2001, 2013, 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 sun.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.Field;36import java.lang.reflect.Executable;37import java.lang.reflect.InvocationTargetException;38import java.lang.reflect.Method;39import java.lang.reflect.Constructor;40import java.lang.reflect.Modifier;41import java.security.AccessController;42import java.security.Permission;43import java.security.PrivilegedAction;44import java.util.Objects;4546import sun.reflect.misc.ReflectUtil;474849/** <P> The master factory for all reflective objects, both those in50java.lang.reflect (Fields, Methods, Constructors) as well as their51delegates (FieldAccessors, MethodAccessors, ConstructorAccessors).52</P>5354<P> The methods in this class are extremely unsafe and can cause55subversion of both the language and the verifier. For this reason,56they are all instance methods, and access to the constructor of57this factory is guarded by a security check, in similar style to58{@link sun.misc.Unsafe}. </P>59*/6061public class ReflectionFactory {6263private static boolean initted = false;64private static final Permission reflectionFactoryAccessPerm65= new RuntimePermission("reflectionFactoryAccess");66private static final ReflectionFactory soleInstance = new ReflectionFactory();67// Provides access to package-private mechanisms in java.lang.reflect68private static volatile LangReflectAccess langReflectAccess;6970/* Method for static class initializer <clinit>, or null */71private static volatile Method hasStaticInitializerMethod;7273//74// "Inflation" mechanism. Loading bytecodes to implement75// Method.invoke() and Constructor.newInstance() currently costs76// 3-4x more than an invocation via native code for the first77// invocation (though subsequent invocations have been benchmarked78// to be over 20x faster). Unfortunately this cost increases79// startup time for certain applications that use reflection80// intensively (but only once per class) to bootstrap themselves.81// To avoid this penalty we reuse the existing JVM entry points82// for the first few invocations of Methods and Constructors and83// then switch to the bytecode-based implementations.84//85// Package-private to be accessible to NativeMethodAccessorImpl86// and NativeConstructorAccessorImpl87private static boolean noInflation = false;88private static int inflationThreshold = 15;8990private ReflectionFactory() {}9192/**93* A convenience class for acquiring the capability to instantiate94* reflective objects. Use this instead of a raw call to {@link95* #getReflectionFactory} in order to avoid being limited by the96* permissions of your callers.97*98* <p>An instance of this class can be used as the argument of99* <code>AccessController.doPrivileged</code>.100*/101public static final class GetReflectionFactoryAction102implements PrivilegedAction<ReflectionFactory> {103public ReflectionFactory run() {104return getReflectionFactory();105}106}107108/**109* Provides the caller with the capability to instantiate reflective110* objects.111*112* <p> First, if there is a security manager, its113* <code>checkPermission</code> method is called with a {@link114* java.lang.RuntimePermission} with target115* <code>"reflectionFactoryAccess"</code>. This may result in a116* security exception.117*118* <p> The returned <code>ReflectionFactory</code> object should be119* carefully guarded by the caller, since it can be used to read and120* write private data and invoke private methods, as well as to load121* unverified bytecodes. It must never be passed to untrusted code.122*123* @exception SecurityException if a security manager exists and its124* <code>checkPermission</code> method doesn't allow125* access to the RuntimePermission "reflectionFactoryAccess". */126public static ReflectionFactory getReflectionFactory() {127SecurityManager security = System.getSecurityManager();128if (security != null) {129// TO DO: security.checkReflectionFactoryAccess();130security.checkPermission(reflectionFactoryAccessPerm);131}132return soleInstance;133}134135//--------------------------------------------------------------------------136//137// Routines used by java.lang.reflect138//139//140141/** Called only by java.lang.reflect.Modifier's static initializer */142public void setLangReflectAccess(LangReflectAccess access) {143langReflectAccess = access;144}145146/**147* Note: this routine can cause the declaring class for the field148* be initialized and therefore must not be called until the149* first get/set of this field.150* @param field the field151* @param override true if caller has overridden aaccessibility152*/153public FieldAccessor newFieldAccessor(Field field, boolean override) {154checkInitted();155return UnsafeFieldAccessorFactory.newFieldAccessor(field, override);156}157158public MethodAccessor newMethodAccessor(Method method) {159checkInitted();160161if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {162return new MethodAccessorGenerator().163generateMethod(method.getDeclaringClass(),164method.getName(),165method.getParameterTypes(),166method.getReturnType(),167method.getExceptionTypes(),168method.getModifiers());169} else {170NativeMethodAccessorImpl acc =171new NativeMethodAccessorImpl(method);172DelegatingMethodAccessorImpl res =173new DelegatingMethodAccessorImpl(acc);174acc.setParent(res);175return res;176}177}178179public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {180checkInitted();181182Class<?> declaringClass = c.getDeclaringClass();183if (Modifier.isAbstract(declaringClass.getModifiers())) {184return new InstantiationExceptionConstructorAccessorImpl(null);185}186if (declaringClass == Class.class) {187return new InstantiationExceptionConstructorAccessorImpl188("Can not instantiate java.lang.Class");189}190// Bootstrapping issue: since we use Class.newInstance() in191// the ConstructorAccessor generation process, we have to192// break the cycle here.193if (Reflection.isSubclassOf(declaringClass,194ConstructorAccessorImpl.class)) {195return new BootstrapConstructorAccessorImpl(c);196}197198if (noInflation && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {199return new MethodAccessorGenerator().200generateConstructor(c.getDeclaringClass(),201c.getParameterTypes(),202c.getExceptionTypes(),203c.getModifiers());204} else {205NativeConstructorAccessorImpl acc =206new NativeConstructorAccessorImpl(c);207DelegatingConstructorAccessorImpl res =208new DelegatingConstructorAccessorImpl(acc);209acc.setParent(res);210return res;211}212}213214//--------------------------------------------------------------------------215//216// Routines used by java.lang217//218//219220/** Creates a new java.lang.reflect.Field. Access checks as per221java.lang.reflect.AccessibleObject are not overridden. */222public Field newField(Class<?> declaringClass,223String name,224Class<?> type,225int modifiers,226int slot,227String signature,228byte[] annotations)229{230return langReflectAccess().newField(declaringClass,231name,232type,233modifiers,234slot,235signature,236annotations);237}238239/** Creates a new java.lang.reflect.Method. Access checks as per240java.lang.reflect.AccessibleObject are not overridden. */241public Method newMethod(Class<?> declaringClass,242String name,243Class<?>[] parameterTypes,244Class<?> returnType,245Class<?>[] checkedExceptions,246int modifiers,247int slot,248String signature,249byte[] annotations,250byte[] parameterAnnotations,251byte[] annotationDefault)252{253return langReflectAccess().newMethod(declaringClass,254name,255parameterTypes,256returnType,257checkedExceptions,258modifiers,259slot,260signature,261annotations,262parameterAnnotations,263annotationDefault);264}265266/** Creates a new java.lang.reflect.Constructor. Access checks as267per java.lang.reflect.AccessibleObject are not overridden. */268public Constructor<?> newConstructor(Class<?> declaringClass,269Class<?>[] parameterTypes,270Class<?>[] checkedExceptions,271int modifiers,272int slot,273String signature,274byte[] annotations,275byte[] parameterAnnotations)276{277return langReflectAccess().newConstructor(declaringClass,278parameterTypes,279checkedExceptions,280modifiers,281slot,282signature,283annotations,284parameterAnnotations);285}286287/** Gets the MethodAccessor object for a java.lang.reflect.Method */288public MethodAccessor getMethodAccessor(Method m) {289return langReflectAccess().getMethodAccessor(m);290}291292/** Sets the MethodAccessor object for a java.lang.reflect.Method */293public void setMethodAccessor(Method m, MethodAccessor accessor) {294langReflectAccess().setMethodAccessor(m, accessor);295}296297/** Gets the ConstructorAccessor object for a298java.lang.reflect.Constructor */299public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {300return langReflectAccess().getConstructorAccessor(c);301}302303/** Sets the ConstructorAccessor object for a304java.lang.reflect.Constructor */305public void setConstructorAccessor(Constructor<?> c,306ConstructorAccessor accessor)307{308langReflectAccess().setConstructorAccessor(c, accessor);309}310311/** Makes a copy of the passed method. The returned method is a312"child" of the passed one; see the comments in Method.java for313details. */314public Method copyMethod(Method arg) {315return langReflectAccess().copyMethod(arg);316}317318/** Makes a copy of the passed field. The returned field is a319"child" of the passed one; see the comments in Field.java for320details. */321public Field copyField(Field arg) {322return langReflectAccess().copyField(arg);323}324325/** Makes a copy of the passed constructor. The returned326constructor is a "child" of the passed one; see the comments327in Constructor.java for details. */328public <T> Constructor<T> copyConstructor(Constructor<T> arg) {329return langReflectAccess().copyConstructor(arg);330}331332/** Gets the byte[] that encodes TypeAnnotations on an executable.333*/334public byte[] getExecutableTypeAnnotationBytes(Executable ex) {335return langReflectAccess().getExecutableTypeAnnotationBytes(ex);336}337338//--------------------------------------------------------------------------339//340// Routines used by serialization341//342//343344/**345* Returns an accessible constructor capable of creating instances346* of the given class, initialized by the given constructor.347*348* @param classToInstantiate the class to instantiate349* @param constructorToCall the constructor to call350* @return an accessible constructor351*/352public Constructor<?> newConstructorForSerialization353(Class<?> classToInstantiate, Constructor<?> constructorToCall)354{355// Fast path356if (constructorToCall.getDeclaringClass() == classToInstantiate) {357return constructorToCall;358}359return generateConstructor(classToInstantiate, constructorToCall);360}361362/**363* Returns an accessible no-arg constructor for a class.364* The no-arg constructor is found searching the class and its supertypes.365*366* @param cl the class to instantiate367* @return a no-arg constructor for the class or {@code null} if368* the class or supertypes do not have a suitable no-arg constructor369*/370public final Constructor<?> newConstructorForSerialization(Class<?> cl) {371Class<?> initCl = cl;372while (Serializable.class.isAssignableFrom(initCl)) {373if ((initCl = initCl.getSuperclass()) == null) {374return null;375}376}377Constructor<?> constructorToCall;378try {379constructorToCall = initCl.getDeclaredConstructor();380int mods = constructorToCall.getModifiers();381if ((mods & Modifier.PRIVATE) != 0 ||382((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&383!packageEquals(cl, initCl))) {384return null;385}386} catch (NoSuchMethodException ex) {387return null;388}389return generateConstructor(cl, constructorToCall);390}391392private final Constructor<?> generateConstructor(Class<?> classToInstantiate,393Constructor<?> constructorToCall) {394395396ConstructorAccessor acc = new MethodAccessorGenerator().397generateSerializationConstructor(classToInstantiate,398constructorToCall.getParameterTypes(),399constructorToCall.getExceptionTypes(),400constructorToCall.getModifiers(),401constructorToCall.getDeclaringClass());402Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(),403constructorToCall.getParameterTypes(),404constructorToCall.getExceptionTypes(),405constructorToCall.getModifiers(),406langReflectAccess().407getConstructorSlot(constructorToCall),408langReflectAccess().409getConstructorSignature(constructorToCall),410langReflectAccess().411getConstructorAnnotations(constructorToCall),412langReflectAccess().413getConstructorParameterAnnotations(constructorToCall));414setConstructorAccessor(c, acc);415c.setAccessible(true);416return c;417}418419/**420* Returns an accessible no-arg constructor for an externalizable class to be421* initialized using a public no-argument constructor.422*423* @param cl the class to instantiate424* @return A no-arg constructor for the class; returns {@code null} if425* the class does not implement {@link java.io.Externalizable}426*/427public final Constructor<?> newConstructorForExternalization(Class<?> cl) {428if (!Externalizable.class.isAssignableFrom(cl)) {429return null;430}431try {432Constructor<?> cons = cl.getConstructor();433cons.setAccessible(true);434return cons;435} catch (NoSuchMethodException ex) {436return null;437}438}439440/**441* Returns a direct MethodHandle for the {@code readObject} method on442* a Serializable class.443* The first argument of {@link MethodHandle#invoke} is the serializable444* object and the second argument is the {@code ObjectInputStream} passed to445* {@code readObject}.446*447* @param cl a Serializable class448* @return a direct MethodHandle for the {@code readObject} method of the class or449* {@code null} if the class does not have a {@code readObject} method450*/451public final MethodHandle readObjectForSerialization(Class<?> cl) {452return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);453}454455/**456* Returns a direct MethodHandle for the {@code readObjectNoData} method on457* a Serializable class.458* The first argument of {@link MethodHandle#invoke} is the serializable459* object and the second argument is the {@code ObjectInputStream} passed to460* {@code readObjectNoData}.461*462* @param cl a Serializable class463* @return a direct MethodHandle for the {@code readObjectNoData} method464* of the class or {@code null} if the class does not have a465* {@code readObjectNoData} method466*/467public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {468return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);469}470471/**472* Returns a direct MethodHandle for the {@code writeObject} method on473* a Serializable class.474* The first argument of {@link MethodHandle#invoke} is the serializable475* object and the second argument is the {@code ObjectOutputStream} passed to476* {@code writeObject}.477*478* @param cl a Serializable class479* @return a direct MethodHandle for the {@code writeObject} method of the class or480* {@code null} if the class does not have a {@code writeObject} method481*/482public final MethodHandle writeObjectForSerialization(Class<?> cl) {483return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);484}485486private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,487String methodName,488Class<?> streamClass) {489if (!Serializable.class.isAssignableFrom(cl)) {490return null;491}492493try {494Method meth = cl.getDeclaredMethod(methodName, streamClass);495int mods = meth.getModifiers();496if (meth.getReturnType() != Void.TYPE ||497Modifier.isStatic(mods) ||498!Modifier.isPrivate(mods)) {499return null;500}501meth.setAccessible(true);502return MethodHandles.lookup().unreflect(meth);503} catch (NoSuchMethodException ex) {504return null;505} catch (IllegalAccessException ex1) {506throw new InternalError("Error", ex1);507}508}509510/**511* Returns a direct MethodHandle for the {@code readResolve} method on512* a serializable class.513* The single argument of {@link MethodHandle#invoke} is the serializable514* object.515*516* @param cl the Serializable class517* @return a direct MethodHandle for the {@code readResolve} method of the class or518* {@code null} if the class does not have a {@code readResolve} method519*/520public final MethodHandle readResolveForSerialization(Class<?> cl) {521return getReplaceResolveForSerialization(cl, "readResolve");522}523524/**525* Returns a direct MethodHandle for the {@code writeReplace} method on526* a serializable class.527* The single argument of {@link MethodHandle#invoke} is the serializable528* object.529*530* @param cl the Serializable class531* @return a direct MethodHandle for the {@code writeReplace} method of the class or532* {@code null} if the class does not have a {@code writeReplace} method533*/534public final MethodHandle writeReplaceForSerialization(Class<?> cl) {535return getReplaceResolveForSerialization(cl, "writeReplace");536}537538/**539* Returns a direct MethodHandle for the {@code writeReplace} method on540* a serializable class.541* The single argument of {@link MethodHandle#invoke} is the serializable542* object.543*544* @param cl the Serializable class545* @return a direct MethodHandle for the {@code writeReplace} method of the class or546* {@code null} if the class does not have a {@code writeReplace} method547*/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 class has a static initializer.588* The presence of a static initializer is used to compute the serialVersionUID.589* @param cl a serializable classLook590* @return {@code true} if the class has a static initializer,591* otherwise {@code false}592*/593public final boolean hasStaticInitializerForSerialization(Class<?> cl) {594Method m = hasStaticInitializerMethod;595if (m == null) {596try {597m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",598new Class<?>[]{Class.class});599m.setAccessible(true);600hasStaticInitializerMethod = m;601} catch (NoSuchMethodException ex) {602throw new InternalError("No such method hasStaticInitializer on "603+ ObjectStreamClass.class, ex);604}605}606try {607return (Boolean) m.invoke(null, cl);608} catch (InvocationTargetException | IllegalAccessException ex) {609throw new InternalError("Exception invoking hasStaticInitializer", ex);610}611}612613/**614* Returns a new OptionalDataException with {@code eof} set to {@code true}615* or {@code false}.616* @param bool the value of {@code eof} in the created OptionalDataException617* @return a new OptionalDataException618*/619public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {620try {621Constructor<OptionalDataException> boolCtor =622OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);623boolCtor.setAccessible(true);624return boolCtor.newInstance(bool);625} catch (NoSuchMethodException | InstantiationException|626IllegalAccessException|InvocationTargetException ex) {627throw new InternalError("unable to create OptionalDataException", ex);628}629}630631//--------------------------------------------------------------------------632//633// Internals only below this point634//635636static int inflationThreshold() {637return inflationThreshold;638}639640/** We have to defer full initialization of this class until after641the static initializer is run since java.lang.reflect.Method's642static initializer (more properly, that for643java.lang.reflect.AccessibleObject) causes this class's to be644run, before the system properties are set up. */645private static void checkInitted() {646if (initted) return;647AccessController.doPrivileged(648new PrivilegedAction<Void>() {649public Void run() {650// Tests to ensure the system properties table is fully651// initialized. This is needed because reflection code is652// called very early in the initialization process (before653// command-line arguments have been parsed and therefore654// these user-settable properties installed.) We assume that655// if System.out is non-null then the System class has been656// fully initialized and that the bulk of the startup code657// has been run.658659if (System.out == null) {660// java.lang.System not yet fully initialized661return null;662}663664String val = System.getProperty("sun.reflect.noInflation");665if (val != null && val.equals("true")) {666noInflation = true;667}668669val = System.getProperty("sun.reflect.inflationThreshold");670if (val != null) {671try {672inflationThreshold = Integer.parseInt(val);673} catch (NumberFormatException e) {674throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);675}676}677678initted = true;679return null;680}681});682}683684private static LangReflectAccess langReflectAccess() {685if (langReflectAccess == null) {686// Call a static method to get class java.lang.reflect.Modifier687// initialized. Its static initializer will cause688// setLangReflectAccess() to be called from the context of the689// java.lang.reflect package.690Modifier.isPublic(Modifier.PUBLIC);691}692return langReflectAccess;693}694695/**696* Returns true if classes are defined in the classloader and same package, false697* otherwise.698* @param cl1 a class699* @param cl2 another class700* @returns true if the two classes are in the same classloader and package701*/702private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {703return cl1.getClassLoader() == cl2.getClassLoader() &&704Objects.equals(cl1.getPackage(), cl2.getPackage());705}706707}708709710