Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/reflect/Reflection.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.lang.reflect.*;28import java.util.HashMap;29import java.util.Map;3031/** Common utility routines used by both java.lang and32java.lang.reflect */3334public class Reflection {3536/** Used to filter out fields and methods from certain classes from public37view, where they are sensitive or they may contain VM-internal objects.38These Maps are updated very rarely. Rather than synchronize on39each access, we use copy-on-write */40private static volatile Map<Class<?>,String[]> fieldFilterMap;41private static volatile Map<Class<?>,String[]> methodFilterMap;4243static {44Map<Class<?>,String[]> map = new HashMap<Class<?>,String[]>();45map.put(Reflection.class,46new String[] {"fieldFilterMap", "methodFilterMap"});47map.put(System.class, new String[] {"security"});48map.put(Class.class, new String[] {"classLoader"});49fieldFilterMap = map;5051methodFilterMap = new HashMap<>();52}5354/** Returns the class of the caller of the method calling this method,55ignoring frames associated with java.lang.reflect.Method.invoke()56and its implementation. */57@CallerSensitive58public static native Class<?> getCallerClass();5960/**61* @deprecated This method will be removed in JDK 9.62* This method is a private JDK API and retained temporarily for63* existing code to run until a replacement API is defined.64*/65@Deprecated66public static native Class<?> getCallerClass(int depth);6768/** Retrieves the access flags written to the class file. For69inner classes these flags may differ from those returned by70Class.getModifiers(), which searches the InnerClasses71attribute to find the source-level access flags. This is used72instead of Class.getModifiers() for run-time access checks due73to compatibility reasons; see 4471811. Only the values of the74low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be75valid. */76public static native int getClassAccessFlags(Class<?> c);7778/** A quick "fast-path" check to try to avoid getCallerClass()79calls. */80public static boolean quickCheckMemberAccess(Class<?> memberClass,81int modifiers)82{83return Modifier.isPublic(getClassAccessFlags(memberClass) & modifiers);84}8586public static void ensureMemberAccess(Class<?> currentClass,87Class<?> memberClass,88Object target,89int modifiers)90throws IllegalAccessException91{92if (currentClass == null || memberClass == null) {93throw new InternalError();94}9596if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) {97throw new IllegalAccessException("Class " + currentClass.getName() +98" can not access a member of class " +99memberClass.getName() +100" with modifiers \"" +101Modifier.toString(modifiers) +102"\"");103}104}105106public static boolean verifyMemberAccess(Class<?> currentClass,107// Declaring class of field108// or method109Class<?> memberClass,110// May be NULL in case of statics111Object target,112int modifiers)113{114// Verify that currentClass can access a field, method, or115// constructor of memberClass, where that member's access bits are116// "modifiers".117118boolean gotIsSameClassPackage = false;119boolean isSameClassPackage = false;120121if (currentClass == memberClass) {122// Always succeeds123return true;124}125126if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {127isSameClassPackage = isSameClassPackage(currentClass, memberClass);128gotIsSameClassPackage = true;129if (!isSameClassPackage) {130return false;131}132}133134// At this point we know that currentClass can access memberClass.135136if (Modifier.isPublic(modifiers)) {137return true;138}139140boolean successSoFar = false;141142if (Modifier.isProtected(modifiers)) {143// See if currentClass is a subclass of memberClass144if (isSubclassOf(currentClass, memberClass)) {145successSoFar = true;146}147}148149if (!successSoFar && !Modifier.isPrivate(modifiers)) {150if (!gotIsSameClassPackage) {151isSameClassPackage = isSameClassPackage(currentClass,152memberClass);153gotIsSameClassPackage = true;154}155156if (isSameClassPackage) {157successSoFar = true;158}159}160161if (!successSoFar) {162return false;163}164165if (Modifier.isProtected(modifiers)) {166// Additional test for protected members: JLS 6.6.2167Class<?> targetClass = (target == null ? memberClass : target.getClass());168if (targetClass != currentClass) {169if (!gotIsSameClassPackage) {170isSameClassPackage = isSameClassPackage(currentClass, memberClass);171gotIsSameClassPackage = true;172}173if (!isSameClassPackage) {174if (!isSubclassOf(targetClass, currentClass)) {175return false;176}177}178}179}180181return true;182}183184private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {185return isSameClassPackage(c1.getClassLoader(), c1.getName(),186c2.getClassLoader(), c2.getName());187}188189/** Returns true if two classes are in the same package; classloader190and classname information is enough to determine a class's package */191private static boolean isSameClassPackage(ClassLoader loader1, String name1,192ClassLoader loader2, String name2)193{194if (loader1 != loader2) {195return false;196} else {197int lastDot1 = name1.lastIndexOf('.');198int lastDot2 = name2.lastIndexOf('.');199if ((lastDot1 == -1) || (lastDot2 == -1)) {200// One of the two doesn't have a package. Only return true201// if the other one also doesn't have a package.202return (lastDot1 == lastDot2);203} else {204int idx1 = 0;205int idx2 = 0;206207// Skip over '['s208if (name1.charAt(idx1) == '[') {209do {210idx1++;211} while (name1.charAt(idx1) == '[');212if (name1.charAt(idx1) != 'L') {213// Something is terribly wrong. Shouldn't be here.214throw new InternalError("Illegal class name " + name1);215}216}217if (name2.charAt(idx2) == '[') {218do {219idx2++;220} while (name2.charAt(idx2) == '[');221if (name2.charAt(idx2) != 'L') {222// Something is terribly wrong. Shouldn't be here.223throw new InternalError("Illegal class name " + name2);224}225}226227// Check that package part is identical228int length1 = lastDot1 - idx1;229int length2 = lastDot2 - idx2;230231if (length1 != length2) {232return false;233}234return name1.regionMatches(false, idx1, name2, idx2, length1);235}236}237}238239static boolean isSubclassOf(Class<?> queryClass,240Class<?> ofClass)241{242while (queryClass != null) {243if (queryClass == ofClass) {244return true;245}246queryClass = queryClass.getSuperclass();247}248return false;249}250251// fieldNames must contain only interned Strings252public static synchronized void registerFieldsToFilter(Class<?> containingClass,253String ... fieldNames) {254fieldFilterMap =255registerFilter(fieldFilterMap, containingClass, fieldNames);256}257258// methodNames must contain only interned Strings259public static synchronized void registerMethodsToFilter(Class<?> containingClass,260String ... methodNames) {261methodFilterMap =262registerFilter(methodFilterMap, containingClass, methodNames);263}264265private static Map<Class<?>,String[]> registerFilter(Map<Class<?>,String[]> map,266Class<?> containingClass, String ... names) {267if (map.get(containingClass) != null) {268throw new IllegalArgumentException269("Filter already registered: " + containingClass);270}271map = new HashMap<Class<?>,String[]>(map);272map.put(containingClass, names);273return map;274}275276public static Field[] filterFields(Class<?> containingClass,277Field[] fields) {278if (fieldFilterMap == null) {279// Bootstrapping280return fields;281}282return (Field[])filter(fields, fieldFilterMap.get(containingClass));283}284285public static Method[] filterMethods(Class<?> containingClass, Method[] methods) {286if (methodFilterMap == null) {287// Bootstrapping288return methods;289}290return (Method[])filter(methods, methodFilterMap.get(containingClass));291}292293private static Member[] filter(Member[] members, String[] filteredNames) {294if ((filteredNames == null) || (members.length == 0)) {295return members;296}297int numNewMembers = 0;298for (Member member : members) {299boolean shouldSkip = false;300for (String filteredName : filteredNames) {301if (member.getName() == filteredName) {302shouldSkip = true;303break;304}305}306if (!shouldSkip) {307++numNewMembers;308}309}310Member[] newMembers =311(Member[])Array.newInstance(members[0].getClass(), numNewMembers);312int destIdx = 0;313for (Member member : members) {314boolean shouldSkip = false;315for (String filteredName : filteredNames) {316if (member.getName() == filteredName) {317shouldSkip = true;318break;319}320}321if (!shouldSkip) {322newMembers[destIdx++] = member;323}324}325return newMembers;326}327328/**329* Tests if the given method is caller-sensitive and the declaring class330* is defined by either the bootstrap class loader or extension class loader.331*/332public static boolean isCallerSensitive(Method m) {333final ClassLoader loader = m.getDeclaringClass().getClassLoader();334if (sun.misc.VM.isSystemDomainLoader(loader) || isExtClassLoader(loader)) {335return m.isAnnotationPresent(CallerSensitive.class);336}337return false;338}339340private static boolean isExtClassLoader(ClassLoader loader) {341ClassLoader cl = ClassLoader.getSystemClassLoader();342while (cl != null) {343if (cl.getParent() == null && cl == loader) {344return true;345}346cl = cl.getParent();347}348return false;349}350}351352353