< prev index next >

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

Print this page

        

*** 43,53 **** import java.io.InputStream; import java.io.ObjectStreamField; 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; --- 43,52 ----
*** 429,439 **** "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( --- 428,440 ---- "Can not call newInstance() on the Class for java.lang.Class" ); } try { Class<?>[] empty = {}; ! // must copy constructor since we are modifying it ! 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(
*** 862,883 **** * 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(); --- 863,888 ---- * returned in that order. * * @return an array of interfaces directly implemented by this class */ public Class<?>[] getInterfaces() { + 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 cached array before handing over to user code ! return cloneArray ? interfaces.clone() : interfaces; } } private native Class<?>[] getInterfaces0();
*** 1746,1756 **** 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 --- 1751,1761 ---- 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
*** 1829,1839 **** 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 --- 1834,1844 ---- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Method method = getMethod0(name, parameterTypes, true); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } ! return getReflectionFactory().copyMethod(method); } /** * Returns a {@code Constructor} object that reflects the specified
*** 1866,1876 **** */ @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 --- 1871,1882 ---- */ @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
*** 2113,2123 **** 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 --- 2119,2129 ---- 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
*** 2173,2183 **** 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 --- 2179,2189 ---- 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
*** 2219,2229 **** */ @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. The rules for searching resources * associated with a given class are implemented by the defining --- 2225,2236 ---- */ @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. The rules for searching resources * associated with a given class are implemented by the defining
*** 2659,2669 **** // Local fields Field[] tmp = privateGetDeclaredFields(true); addAll(fields, tmp); // Direct superinterfaces, recursively ! for (Class<?> c : getInterfaces()) { if (!traversedInterfaces.contains(c)) { traversedInterfaces.add(c); addAll(fields, c.privateGetPublicFields(traversedInterfaces)); } } --- 2666,2676 ---- // Local fields Field[] tmp = privateGetDeclaredFields(true); addAll(fields, tmp); // Direct superinterfaces, recursively ! for (Class<?> c : getInterfaces(false)) { if (!traversedInterfaces.contains(c)) { traversedInterfaces.add(c); addAll(fields, c.privateGetPublicFields(traversedInterfaces)); } }
*** 2753,2935 **** } } 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() { --- 2760,2770 ---- } } return res; } ! private static final Method[] EMPTY_METHODS = new Method[0]; // 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() {
*** 2939,2994 **** if (rd != null) { 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; } --- 2774,2836 ---- if (rd != null) { res = rd.publicMethods; if (res != null) return res; } ! Method[] declaredMethods = privateGetDeclaredMethods(true); ! Class<?> superclass = getSuperclass(); ! Class<?>[] interfaces = getInterfaces(false); ! ! // optimization: ! // if we don't have a superclass (either we are j.l.Object or an interface) ! // and don't have (super)interfaces either, then public methods consist ! // of declared public methods ! if (superclass == null && interfaces.length == 0) { ! res = declaredMethods; ! } else { ! // we have to do some logic ! Method[] superclassMethods = (superclass == null) ! ? EMPTY_METHODS ! : superclass.privateGetPublicMethods(); ! Method[][] interfacesMethods = new Method[interfaces.length][]; ! int interfacesMethodsCount = 0; ! for (int i = 0; i < interfaces.length; i++) { ! interfacesMethods[i] = interfaces[i].privateGetPublicMethods(); ! interfacesMethodsCount += interfacesMethods[i].length; ! } ! ! // ensure enough working capacity ! // (MethodTable implementation may not support dynamic resizing) ! MethodTable methodTable = MethodTable.newInstance( ! declaredMethods.length + ! superclassMethods.length + ! interfacesMethodsCount ! ); ! ! // declared methods first ! for (Method m : declaredMethods) { ! methodTable.add(m); } ! ! // inherited methods from superclass ! for (Method m : superclassMethods) { ! methodTable.addUnlessDeclaredExists(m, this); } ! ! // inherited methods from (super)interfaces ! for (Method[] ms : interfacesMethods) { ! for (Method m : ms) { ! // interface static methods are not inherited ! if (!Modifier.isStatic(m.getModifiers())) { ! methodTable.consolidate(m, this); ! } ! } ! } ! ! res = methodTable.getMethods(); ! } ! if (rd != null) { rd.publicMethods = res; } return res; }
*** 2996,3015 **** // // 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 --- 2838,2866 ---- // // Helpers for fetchers of one field, method, or constructor // + /** + * This method does not copy returned 'root' Field object. It MUST be copied + * with ReflectionFactory before handed to any code outside java.lang.Class + * or modified. + */ private static Field searchFields(Field[] fields, String name) { String internedName = name.intern(); for (Field field : fields) { if (field.getName() == internedName) { ! return field; } } return null; } + /** + * This method returns 'root' Field object. It MUST be copied with ReflectionFactory + * before handed to any code outside java.lang.Class or modified. + */ 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
*** 3020,3030 **** // 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; } } --- 2871,2881 ---- // Search declared public fields if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; } // Direct superinterfaces, recursively ! Class<?>[] interfaces = getInterfaces(false); for (Class<?> c : interfaces) { if ((res = c.getField0(name)) != null) { return res; } }
*** 3038,3047 **** --- 2889,2903 ---- } } return null; } + /** + * This method does not copy returned 'root' Method object. It MUST be copied + * with ReflectionFactory before handed to any code outside java.lang.Class + * or modified. + */ private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes) { Method res = null;
*** 3052,3128 **** && (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)); } --- 2908,2979 ---- && (res == null || res.getReturnType().isAssignableFrom(m.getReturnType()))) res = m; } return res; } ! /** ! * This method returns 'root' Method object. It MUST be copied with ReflectionFactory ! * before handed to any code outside java.lang.Class or modified. ! */ ! private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) { // 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. Method res; ! // 1st search declared public methods if ((res = searchMethods(privateGetDeclaredMethods(true), name, ! parameterTypes)) != null && ! (includeStaticMethods || ! !Modifier.isStatic(res.getModifiers()))) { return res; } ! ! // 2nd we try the superclass. ! Class<? super T> superclass = getSuperclass(); ! if (superclass != null && ! (res = superclass.getMethod0(name, parameterTypes, includeStaticMethods)) != null) { return res; } + + // last we check (super) interfaces + Class<?>[] interfaces = getInterfaces(false); + if (interfaces.length == 0) { + return null; + } + // have to construct a MethodTable to consolidate + // public methods from (super)interfaces + MethodTable methodTable = MethodTable.newInstance(interfaces.length); + for (Class<?> c : interfaces) { + if ((res = c.getMethod0(name, parameterTypes, false)) != null) { + methodTable.consolidate(res, this); } } ! ! // return the first method with the most specific return type ! return methodTable.getFirstMethodWithMostSpecificReturnType(); } + /** + * This method returns 'root' Constructor object. It MUST be copied with ReflectionFactory + * before handed to any code outside java.lang.Class or modified. + */ 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 constructor; } } throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes)); }
< prev index next >