< prev index next >

src/java.base/share/classes/java/lang/Class.java

Print this page

        

*** 49,59 **** import java.io.ObjectStreamField; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; - import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Set; --- 49,58 ----
*** 532,542 **** "Can not call newInstance() on the Class for java.lang.Class" ); } try { Class<?>[] empty = {}; ! final Constructor<T> c = getConstructor0(empty, Member.DECLARED); // Disable accessibility checks on the constructor // since we have to do the security check here anyway // (the stack depth is wrong for the Constructor's // security check to work) java.security.AccessController.doPrivileged( --- 531,542 ---- "Can not call newInstance() on the Class for java.lang.Class" ); } try { Class<?>[] empty = {}; ! final Constructor<T> c = getReflectionFactory().copyConstructor( ! getConstructor0(empty, Member.DECLARED)); // Disable accessibility checks on the constructor // since we have to do the security check here anyway // (the stack depth is wrong for the Constructor's // security check to work) java.security.AccessController.doPrivileged(
*** 1024,1045 **** * returned in that order. * * @return an array of interfaces directly implemented by this class */ public Class<?>[] getInterfaces() { ReflectionData<T> rd = reflectionData(); if (rd == null) { // no cloning required return getInterfaces0(); } else { Class<?>[] interfaces = rd.interfaces; if (interfaces == null) { interfaces = getInterfaces0(); rd.interfaces = interfaces; } ! // defensively copy before handing over to user code ! return interfaces.clone(); } } private native Class<?>[] getInterfaces0(); --- 1024,1050 ---- * returned in that order. * * @return an array of interfaces directly implemented by this class */ public Class<?>[] getInterfaces() { + // defensively copy before handing over to user code + return getInterfaces(true); + } + + private Class<?>[] getInterfaces(boolean cloneArray) { ReflectionData<T> rd = reflectionData(); if (rd == null) { // no cloning required return getInterfaces0(); } else { Class<?>[] interfaces = rd.interfaces; if (interfaces == null) { interfaces = getInterfaces0(); rd.interfaces = interfaces; } ! // defensively copy if requested ! return cloneArray ? interfaces.clone() : interfaces; } } private native Class<?>[] getInterfaces0();
*** 1888,1898 **** checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Field field = getField0(name); if (field == null) { throw new NoSuchFieldException(name); } ! return field; } /** * Returns a {@code Method} object that reflects the specified public --- 1893,1903 ---- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Field field = getField0(name); if (field == null) { throw new NoSuchFieldException(name); } ! return getReflectionFactory().copyField(field); } /** * Returns a {@code Method} object that reflects the specified public
*** 1967,1981 **** */ @CallerSensitive public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); ! Method method = getMethod0(name, parameterTypes, true); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } ! return method; } /** * Returns a {@code Constructor} object that reflects the specified --- 1972,1986 ---- */ @CallerSensitive public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); ! Method method = getMethod0(name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } ! return getReflectionFactory().copyMethod(method); } /** * Returns a {@code Constructor} object that reflects the specified
*** 2008,2018 **** */ @CallerSensitive public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); ! return getConstructor0(parameterTypes, Member.PUBLIC); } /** * Returns an array of {@code Class} objects reflecting all the --- 2013,2024 ---- */ @CallerSensitive public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); ! return getReflectionFactory().copyConstructor( ! getConstructor0(parameterTypes, Member.PUBLIC)); } /** * Returns an array of {@code Class} objects reflecting all the
*** 2255,2265 **** checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { throw new NoSuchFieldException(name); } ! return field; } /** * Returns a {@code Method} object that reflects the specified --- 2261,2271 ---- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { throw new NoSuchFieldException(name); } ! return getReflectionFactory().copyField(field); } /** * Returns a {@code Method} object that reflects the specified
*** 2315,2325 **** checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } ! return method; } /** * Returns a {@code Constructor} object that reflects the specified --- 2321,2331 ---- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } ! return getReflectionFactory().copyMethod(method); } /** * Returns a {@code Constructor} object that reflects the specified
*** 2361,2371 **** */ @CallerSensitive public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); ! return getConstructor0(parameterTypes, Member.DECLARED); } /** * Finds a resource with a given name. If this class is in a named {@link * Module Module}, and the caller of this method is in the same module, --- 2367,2378 ---- */ @CallerSensitive public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); ! return getReflectionFactory().copyConstructor( ! getConstructor0(parameterTypes, Member.DECLARED)); } /** * Finds a resource with a given name. If this class is in a named {@link * Module Module}, and the caller of this method is in the same module,
*** 2954,3137 **** } } return res; } - static class MethodArray { - // Don't add or remove methods except by add() or remove() calls. - private Method[] methods; - private int length; - private int defaults; - - MethodArray() { - this(20); - } - - MethodArray(int initialSize) { - if (initialSize < 2) - throw new IllegalArgumentException("Size should be 2 or more"); - - methods = new Method[initialSize]; - length = 0; - defaults = 0; - } - - boolean hasDefaults() { - return defaults != 0; - } - - void add(Method m) { - if (length == methods.length) { - methods = Arrays.copyOf(methods, 2 * methods.length); - } - methods[length++] = m; - - if (m != null && m.isDefault()) - defaults++; - } - - void addAll(Method[] ma) { - for (Method m : ma) { - add(m); - } - } - - void addAll(MethodArray ma) { - for (int i = 0; i < ma.length(); i++) { - add(ma.get(i)); - } - } - - void addIfNotPresent(Method newMethod) { - for (int i = 0; i < length; i++) { - Method m = methods[i]; - if (m == newMethod || (m != null && m.equals(newMethod))) { - return; - } - } - add(newMethod); - } - - void addAllIfNotPresent(MethodArray newMethods) { - for (int i = 0; i < newMethods.length(); i++) { - Method m = newMethods.get(i); - if (m != null) { - addIfNotPresent(m); - } - } - } - - /* Add Methods declared in an interface to this MethodArray. - * Static methods declared in interfaces are not inherited. - */ - void addInterfaceMethods(Method[] methods) { - for (Method candidate : methods) { - if (!Modifier.isStatic(candidate.getModifiers())) { - add(candidate); - } - } - } - - int length() { - return length; - } - - Method get(int i) { - return methods[i]; - } - - Method getFirst() { - for (Method m : methods) - if (m != null) - return m; - return null; - } - - void removeByNameAndDescriptor(Method toRemove) { - for (int i = 0; i < length; i++) { - Method m = methods[i]; - if (m != null && matchesNameAndDescriptor(m, toRemove)) { - remove(i); - } - } - } - - private void remove(int i) { - if (methods[i] != null && methods[i].isDefault()) - defaults--; - methods[i] = null; - } - - private boolean matchesNameAndDescriptor(Method m1, Method m2) { - return m1.getReturnType() == m2.getReturnType() && - m1.getName() == m2.getName() && // name is guaranteed to be interned - arrayContentsEq(m1.getParameterTypes(), - m2.getParameterTypes()); - } - - void compactAndTrim() { - int newPos = 0; - // Get rid of null slots - for (int pos = 0; pos < length; pos++) { - Method m = methods[pos]; - if (m != null) { - if (pos != newPos) { - methods[newPos] = m; - } - newPos++; - } - } - if (newPos != methods.length) { - methods = Arrays.copyOf(methods, newPos); - } - } - - /* Removes all Methods from this MethodArray that have a more specific - * default Method in this MethodArray. - * - * Users of MethodArray are responsible for pruning Methods that have - * a more specific <em>concrete</em> Method. - */ - void removeLessSpecifics() { - if (!hasDefaults()) - return; - - for (int i = 0; i < length; i++) { - Method m = get(i); - if (m == null || !m.isDefault()) - continue; - - for (int j = 0; j < length; j++) { - if (i == j) - continue; - - Method candidate = get(j); - if (candidate == null) - continue; - - if (!matchesNameAndDescriptor(m, candidate)) - continue; - - if (hasMoreSpecificClass(m, candidate)) - remove(j); - } - } - } - - Method[] getArray() { - return methods; - } - - // Returns true if m1 is more specific than m2 - static boolean hasMoreSpecificClass(Method m1, Method m2) { - Class<?> m1Class = m1.getDeclaringClass(); - Class<?> m2Class = m2.getDeclaringClass(); - return m1Class != m2Class && m2Class.isAssignableFrom(m1Class); - } - } - - // Returns an array of "root" methods. These Method objects must NOT // be propagated to the outside world, but must instead be copied // via ReflectionFactory.copyMethod. private Method[] privateGetPublicMethods() { checkInitted(); --- 2961,2970 ----
*** 3141,3195 **** res = rd.publicMethods; if (res != null) return res; } // No cached value available; compute value recursively. ! // Start by fetching public declared methods ! MethodArray methods = new MethodArray(); ! { ! Method[] tmp = privateGetDeclaredMethods(true); ! methods.addAll(tmp); } ! // Now recur over superclass and direct superinterfaces. ! // Go over superinterfaces first so we can more easily filter ! // out concrete implementations inherited from superclasses at ! // the end. ! MethodArray inheritedMethods = new MethodArray(); ! for (Class<?> i : getInterfaces()) { ! inheritedMethods.addInterfaceMethods(i.privateGetPublicMethods()); } ! if (!isInterface()) { ! Class<?> c = getSuperclass(); ! if (c != null) { ! MethodArray supers = new MethodArray(); ! supers.addAll(c.privateGetPublicMethods()); ! // Filter out concrete implementations of any ! // interface methods ! for (int i = 0; i < supers.length(); i++) { ! Method m = supers.get(i); ! if (m != null && ! !Modifier.isAbstract(m.getModifiers()) && ! !m.isDefault()) { ! inheritedMethods.removeByNameAndDescriptor(m); ! } ! } ! // Insert superclass's inherited methods before ! // superinterfaces' to satisfy getMethod's search ! // order ! supers.addAll(inheritedMethods); ! inheritedMethods = supers; ! } ! } ! // Filter out all local methods from inherited ones ! for (int i = 0; i < methods.length(); i++) { ! Method m = methods.get(i); ! inheritedMethods.removeByNameAndDescriptor(m); ! } ! methods.addAllIfNotPresent(inheritedMethods); ! methods.removeLessSpecifics(); ! methods.compactAndTrim(); ! res = methods.getArray(); if (rd != null) { rd.publicMethods = res; } return res; } --- 2974,3006 ---- res = rd.publicMethods; if (res != null) return res; } // No cached value available; compute value recursively. ! // Start by fetching public declared methods... ! PublicMethods pms = new PublicMethods(); ! for (Method m : privateGetDeclaredMethods(/* publicOnly */ true)) { ! pms.consolidate(m); } ! // ...then recur over superclass methods... ! Class<?> sc = getSuperclass(); ! if (sc != null) { ! for (Method m : sc.privateGetPublicMethods()) { ! pms.consolidate(m); } ! } ! // ...and finally over direct superinterfaces. ! for (Class<?> intf : getInterfaces(/* cloneArray */ false)) { ! for (Method m : intf.privateGetPublicMethods()) { ! // static interface methods are not inherited ! if (!Modifier.isStatic(m.getModifiers())) { ! pms.consolidate(m); ! } ! } ! } ! ! res = pms.toArray(); if (rd != null) { rd.publicMethods = res; } return res; }
*** 3197,3217 **** // // Helpers for fetchers of one field, method, or constructor // private static Field searchFields(Field[] fields, String name) { - String internedName = name.intern(); for (Field field : fields) { ! if (field.getName() == internedName) { ! return getReflectionFactory().copyField(field); } } return null; } ! private Field getField0(String name) throws NoSuchFieldException { // Note: the intent is that the search algorithm this routine // uses be equivalent to the ordering imposed by // privateGetPublicFields(). It fetches only the declared // public fields for each class, however, to reduce the number // of Field objects which have to be created for the common --- 3008,3031 ---- // // Helpers for fetchers of one field, method, or constructor // + // This method does not copy the returned Field object! private static Field searchFields(Field[] fields, String name) { for (Field field : fields) { ! if (field.getName().equals(name)) { ! return field; } } return null; } ! // Returns a "root" Field object. This Field object must NOT ! // be propagated to the outside world, but must instead be copied ! // via ReflectionFactory.copyField. ! private Field getField0(String name) { // Note: the intent is that the search algorithm this routine // uses be equivalent to the ordering imposed by // privateGetPublicFields(). It fetches only the declared // public fields for each class, however, to reduce the number // of Field objects which have to be created for the common
*** 3221,3231 **** // Search declared public fields if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; } // Direct superinterfaces, recursively ! Class<?>[] interfaces = getInterfaces(); for (Class<?> c : interfaces) { if ((res = c.getField0(name)) != null) { return res; } } --- 3035,3045 ---- // Search declared public fields if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; } // Direct superinterfaces, recursively ! Class<?>[] interfaces = getInterfaces(/* cloneArray */ false); for (Class<?> c : interfaces) { if ((res = c.getField0(name)) != null) { return res; } }
*** 3239,3329 **** } } return null; } private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes) { Method res = null; - String internedName = name.intern(); for (Method m : methods) { ! if (m.getName() == internedName ! && arrayContentsEq(parameterTypes, m.getParameterTypes()) && (res == null ! || res.getReturnType().isAssignableFrom(m.getReturnType()))) res = m; } ! ! return (res == null ? res : getReflectionFactory().copyMethod(res)); } ! private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) { ! MethodArray interfaceCandidates = new MethodArray(2); ! Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates); ! if (res != null) ! return res; ! // Not found on class or superclass directly ! interfaceCandidates.removeLessSpecifics(); ! return interfaceCandidates.getFirst(); // may be null } ! private Method privateGetMethodRecursive(String name, Class<?>[] parameterTypes, ! boolean includeStaticMethods, ! MethodArray allInterfaceCandidates) { ! // Note: the intent is that the search algorithm this routine ! // uses be equivalent to the ordering imposed by ! // privateGetPublicMethods(). It fetches only the declared ! // public methods for each class, however, to reduce the ! // number of Method objects which have to be created for the ! // common case where the method being requested is declared in ! // the class which is being queried. ! // ! // Due to default methods, unless a method is found on a superclass, ! // methods declared in any superinterface needs to be considered. ! // Collect all candidates declared in superinterfaces in {@code ! // allInterfaceCandidates} and select the most specific if no match on ! // a superclass is found. ! ! // Must _not_ return root methods ! Method res; ! // Search declared public methods ! if ((res = searchMethods(privateGetDeclaredMethods(true), ! name, ! parameterTypes)) != null) { ! if (includeStaticMethods || !Modifier.isStatic(res.getModifiers())) ! return res; ! } ! // Search superclass's methods ! if (!isInterface()) { ! Class<? super T> c = getSuperclass(); ! if (c != null) { ! if ((res = c.getMethod0(name, parameterTypes, true)) != null) { return res; } } } ! // Search superinterfaces' methods ! Class<?>[] interfaces = getInterfaces(); ! for (Class<?> c : interfaces) ! if ((res = c.getMethod0(name, parameterTypes, false)) != null) ! allInterfaceCandidates.add(res); ! // Not found ! return null; } private Constructor<T> getConstructor0(Class<?>[] parameterTypes, int which) throws NoSuchMethodException { Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); for (Constructor<T> constructor : constructors) { if (arrayContentsEq(parameterTypes, ! constructor.getParameterTypes())) { ! return getReflectionFactory().copyConstructor(constructor); } } throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes)); } --- 3053,3141 ---- } } return null; } + // This method does not copy the returned Method object! private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes) { + ReflectionFactory fact = getReflectionFactory(); Method res = null; for (Method m : methods) { ! if (m.getName().equals(name) ! && arrayContentsEq(parameterTypes, ! fact.getExecutableSharedParameterTypes(m)) && (res == null ! || (res.getReturnType() != m.getReturnType() ! && res.getReturnType().isAssignableFrom(m.getReturnType())))) res = m; } ! return res; } ! private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0]; ! // Returns a "root" Method object. This Method object must NOT ! // be propagated to the outside world, but must instead be copied ! // via ReflectionFactory.copyMethod. ! private Method getMethod0(String name, Class<?>[] parameterTypes) { ! PublicMethods.MethodList res = getMethodsRecursive( ! name, ! parameterTypes == null ? EMPTY_CLASS_ARRAY : parameterTypes, ! /* includeStatic */ true); ! return res == null ? null : res.getMostSpecific(); } ! // Returns a list of "root" Method objects. These Method objects must NOT ! // be propagated to the outside world, but must instead be copied ! // via ReflectionFactory.copyMethod. ! private PublicMethods.MethodList getMethodsRecursive(String name, Class<?>[] parameterTypes, ! boolean includeStatic) { ! // 1st check declared public methods ! Method[] methods = privateGetDeclaredMethods(/* publicOnly */ true); ! PublicMethods.MethodList res = PublicMethods.MethodList ! .filter(methods, name, parameterTypes, includeStatic); ! // if there is at least one match among declared methods, we need not ! // search any further as such match surely overrides matching methods ! // declared in superclass(es) or interface(s). ! if (res != null) { return res; } + + // if there was no match among declared methods, + // we must consult the superclass (if any) recursively... + Class<?> sc = getSuperclass(); + if (sc != null) { + res = sc.getMethodsRecursive(name, parameterTypes, includeStatic); } + + // ...and consolidate the superclass methods with methods obtained + // from directly implemented interfaces excluding static methods... + for (Class<?> intf : getInterfaces(/* cloneArray */ false)) { + res = PublicMethods.MethodList.consolidate( + res, intf.getMethodsRecursive(name, parameterTypes, + /* includeStatic */ false)); } ! ! return res; } + // Returns a "root" Constructor object. This Constructor object must NOT + // be propagated to the outside world, but must instead be copied + // via ReflectionFactory.copyConstructor. private Constructor<T> getConstructor0(Class<?>[] parameterTypes, int which) throws NoSuchMethodException { + ReflectionFactory fact = getReflectionFactory(); Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); for (Constructor<T> constructor : constructors) { if (arrayContentsEq(parameterTypes, ! fact.getExecutableSharedParameterTypes(constructor))) { ! return constructor; } } throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes)); }
< prev index next >