2679 checkInitted();
2680 Method[] res;
2681 ReflectionData<T> rd = reflectionData();
2682 if (rd != null) {
2683 res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
2684 if (res != null) return res;
2685 }
2686 // No cached value available; request value from VM
2687 res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
2688 if (rd != null) {
2689 if (publicOnly) {
2690 rd.declaredPublicMethods = res;
2691 } else {
2692 rd.declaredMethods = res;
2693 }
2694 }
2695 return res;
2696 }
2697
2698 static class MethodArray {
2699 private Method[] methods;
2700 private int length;
2701
2702 MethodArray() {
2703 methods = new Method[20];
2704 length = 0;
2705 }
2706
2707 void add(Method m) {
2708 if (length == methods.length) {
2709 methods = Arrays.copyOf(methods, 2 * methods.length);
2710 }
2711 methods[length++] = m;
2712 }
2713
2714 void addAll(Method[] ma) {
2715 for (Method m : ma) {
2716 add(m);
2717 }
2718 }
2719
2720 void addAll(MethodArray ma) {
2721 for (int i = 0; i < ma.length(); i++) {
2722 add(ma.get(i));
2723 }
2724 }
2725
2726 void addIfNotPresent(Method newMethod) {
2727 for (int i = 0; i < length; i++) {
2728 Method m = methods[i];
2729 if (m == newMethod || (m != null && m.equals(newMethod))) {
2730 return;
2731 }
2732 }
2733 add(newMethod);
2734 }
2735
2736 void addAllIfNotPresent(MethodArray newMethods) {
2737 for (int i = 0; i < newMethods.length(); i++) {
2738 Method m = newMethods.get(i);
2739 if (m != null) {
2740 addIfNotPresent(m);
2741 }
2742 }
2743 }
2744
2745 void addAllNonStatic(Method[] methods) {
2746 for (Method candidate : methods) {
2747 if (!Modifier.isStatic(candidate.getModifiers())) {
2748 add(candidate);
2749 }
2750 }
2751 }
2752
2753 int length() {
2754 return length;
2755 }
2756
2757 Method get(int i) {
2758 return methods[i];
2759 }
2760
2761 void removeByNameAndSignature(Method toRemove) {
2762 for (int i = 0; i < length; i++) {
2763 Method m = methods[i];
2764 if (m != null &&
2765 m.getReturnType() == toRemove.getReturnType() &&
2766 m.getName() == toRemove.getName() &&
2767 arrayContentsEq(m.getParameterTypes(),
2768 toRemove.getParameterTypes())) {
2769 methods[i] = null;
2770 }
2771 }
2772 }
2773
2774 void compactAndTrim() {
2775 int newPos = 0;
2776 // Get rid of null slots
2777 for (int pos = 0; pos < length; pos++) {
2778 Method m = methods[pos];
2779 if (m != null) {
2780 if (pos != newPos) {
2781 methods[newPos] = m;
2782 }
2783 newPos++;
2784 }
2785 }
2786 if (newPos != methods.length) {
2787 methods = Arrays.copyOf(methods, newPos);
2788 }
2789 }
2790
2791 Method[] getArray() {
2792 return methods;
2793 }
2794 }
2795
2796
2797 // Returns an array of "root" methods. These Method objects must NOT
2798 // be propagated to the outside world, but must instead be copied
2799 // via ReflectionFactory.copyMethod.
2800 private Method[] privateGetPublicMethods() {
2801 checkInitted();
2802 Method[] res;
2803 ReflectionData<T> rd = reflectionData();
2804 if (rd != null) {
2805 res = rd.publicMethods;
2806 if (res != null) return res;
2807 }
2808
2809 // No cached value available; compute value recursively.
2810 // Start by fetching public declared methods
2811 MethodArray methods = new MethodArray();
2812 {
2813 Method[] tmp = privateGetDeclaredMethods(true);
2814 methods.addAll(tmp);
2815 }
2816 // Now recur over superclass and direct superinterfaces.
2817 // Go over superinterfaces first so we can more easily filter
2818 // out concrete implementations inherited from superclasses at
2819 // the end.
2820 MethodArray inheritedMethods = new MethodArray();
2821 for (Class<?> i : getInterfaces()) {
2822 inheritedMethods.addAllNonStatic(i.privateGetPublicMethods());
2823 }
2824 if (!isInterface()) {
2825 Class<?> c = getSuperclass();
2826 if (c != null) {
2827 MethodArray supers = new MethodArray();
2828 supers.addAll(c.privateGetPublicMethods());
2829 // Filter out concrete implementations of any
2830 // interface methods
2831 for (int i = 0; i < supers.length(); i++) {
2832 Method m = supers.get(i);
2833 if (m != null && !Modifier.isAbstract(m.getModifiers())) {
2834 inheritedMethods.removeByNameAndSignature(m);
2835 }
2836 }
2837 // Insert superclass's inherited methods before
2838 // superinterfaces' to satisfy getMethod's search
2839 // order
2840 supers.addAll(inheritedMethods);
2841 inheritedMethods = supers;
2842 }
2843 }
2844 // Filter out all local methods from inherited ones
2845 for (int i = 0; i < methods.length(); i++) {
2846 Method m = methods.get(i);
2847 inheritedMethods.removeByNameAndSignature(m);
2848 }
2849 methods.addAllIfNotPresent(inheritedMethods);
2850 methods.compactAndTrim();
2851 res = methods.getArray();
2852 if (rd != null) {
2853 rd.publicMethods = res;
2854 }
2855 return res;
2856 }
2857
2858
2859 //
2860 // Helpers for fetchers of one field, method, or constructor
2861 //
2862
2863 private static Field searchFields(Field[] fields, String name) {
2864 String internedName = name.intern();
2865 for (Field field : fields) {
2866 if (field.getName() == internedName) {
2867 return getReflectionFactory().copyField(field);
2868 }
2869 }
2902 return null;
2903 }
2904
2905 private static Method searchMethods(Method[] methods,
2906 String name,
2907 Class<?>[] parameterTypes)
2908 {
2909 Method res = null;
2910 String internedName = name.intern();
2911 for (Method m : methods) {
2912 if (m.getName() == internedName
2913 && arrayContentsEq(parameterTypes, m.getParameterTypes())
2914 && (res == null
2915 || res.getReturnType().isAssignableFrom(m.getReturnType())))
2916 res = m;
2917 }
2918
2919 return (res == null ? res : getReflectionFactory().copyMethod(res));
2920 }
2921
2922
2923 private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
2924 // Note: the intent is that the search algorithm this routine
2925 // uses be equivalent to the ordering imposed by
2926 // privateGetPublicMethods(). It fetches only the declared
2927 // public methods for each class, however, to reduce the
2928 // number of Method objects which have to be created for the
2929 // common case where the method being requested is declared in
2930 // the class which is being queried.
2931 Method res;
2932 // Search declared public methods
2933 if ((res = searchMethods(privateGetDeclaredMethods(true),
2934 name,
2935 parameterTypes)) != null) {
2936 if (includeStaticMethods || !Modifier.isStatic(res.getModifiers()))
2937 return res;
2938 }
2939 // Search superclass's methods
2940 if (!isInterface()) {
2941 Class<? super T> c = getSuperclass();
2942 if (c != null) {
2943 if ((res = c.getMethod0(name, parameterTypes, true)) != null) {
2944 return res;
2945 }
2946 }
2947 }
2948 // Search superinterfaces' methods
2949 Class<?>[] interfaces = getInterfaces();
2950 for (Class<?> c : interfaces)
2951 if ((res = c.getMethod0(name, parameterTypes, false)) != null)
2952 return res;
2953 // Not found
2954 return null;
2955 }
2956
2957 private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
2958 int which) throws NoSuchMethodException
2959 {
2960 Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
2961 for (Constructor<T> constructor : constructors) {
2962 if (arrayContentsEq(parameterTypes,
2963 constructor.getParameterTypes())) {
2964 return getReflectionFactory().copyConstructor(constructor);
2965 }
2966 }
2967 throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
2968 }
2969
2970 //
2971 // Other helpers and base implementation
2972 //
|
2679 checkInitted();
2680 Method[] res;
2681 ReflectionData<T> rd = reflectionData();
2682 if (rd != null) {
2683 res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
2684 if (res != null) return res;
2685 }
2686 // No cached value available; request value from VM
2687 res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
2688 if (rd != null) {
2689 if (publicOnly) {
2690 rd.declaredPublicMethods = res;
2691 } else {
2692 rd.declaredMethods = res;
2693 }
2694 }
2695 return res;
2696 }
2697
2698 static class MethodArray {
2699 // Don't add or remove methods except by add() or remove() calls.
2700 private Method[] methods;
2701 private int length;
2702 private int defaults;
2703
2704 MethodArray() {
2705 this(20);
2706 }
2707
2708 MethodArray(int initialSize) {
2709 if (initialSize < 2)
2710 throw new IllegalArgumentException("Size should be 2 or more");
2711
2712 methods = new Method[initialSize];
2713 length = 0;
2714 defaults = 0;
2715 }
2716
2717 boolean hasDefaults() {
2718 return defaults != 0;
2719 }
2720
2721 void add(Method m) {
2722 if (length == methods.length) {
2723 methods = Arrays.copyOf(methods, 2 * methods.length);
2724 }
2725 methods[length++] = m;
2726
2727 if (m != null && m.isDefault())
2728 defaults++;
2729 }
2730
2731 void addAll(Method[] ma) {
2732 for (Method m : ma) {
2733 add(m);
2734 }
2735 }
2736
2737 void addAll(MethodArray ma) {
2738 for (int i = 0; i < ma.length(); i++) {
2739 add(ma.get(i));
2740 }
2741 }
2742
2743 void addIfNotPresent(Method newMethod) {
2744 for (int i = 0; i < length; i++) {
2745 Method m = methods[i];
2746 if (m == newMethod || (m != null && m.equals(newMethod))) {
2747 return;
2748 }
2749 }
2750 add(newMethod);
2751 }
2752
2753 void addAllIfNotPresent(MethodArray newMethods) {
2754 for (int i = 0; i < newMethods.length(); i++) {
2755 Method m = newMethods.get(i);
2756 if (m != null) {
2757 addIfNotPresent(m);
2758 }
2759 }
2760 }
2761
2762 /* Add Methods declared in an interface to this MethodArray.
2763 * Static methods declared in interfaces are not inherited.
2764 */
2765 void addInterfaceMethods(Method[] methods) {
2766 for (Method candidate : methods) {
2767 if (!Modifier.isStatic(candidate.getModifiers())) {
2768 add(candidate);
2769 }
2770 }
2771 }
2772
2773 int length() {
2774 return length;
2775 }
2776
2777 Method get(int i) {
2778 return methods[i];
2779 }
2780
2781 Method getFirst() {
2782 for (Method m : methods)
2783 if (m != null)
2784 return m;
2785 return null;
2786 }
2787
2788 void removeByNameAndDescriptor(Method toRemove) {
2789 for (int i = 0; i < length; i++) {
2790 Method m = methods[i];
2791 if (m != null && matchesNameAndDescriptor(m, toRemove)) {
2792 remove(i);
2793 }
2794 }
2795 }
2796
2797 private void remove(int i) {
2798 if (methods[i] != null && methods[i].isDefault())
2799 defaults--;
2800 methods[i] = null;
2801 }
2802
2803 private boolean matchesNameAndDescriptor(Method m1, Method m2) {
2804 return m1.getReturnType() == m2.getReturnType() &&
2805 m1.getName() == m2.getName() &&
2806 arrayContentsEq(m1.getParameterTypes(),
2807 m2.getParameterTypes());
2808 }
2809
2810 void compactAndTrim() {
2811 int newPos = 0;
2812 // Get rid of null slots
2813 for (int pos = 0; pos < length; pos++) {
2814 Method m = methods[pos];
2815 if (m != null) {
2816 if (pos != newPos) {
2817 methods[newPos] = m;
2818 }
2819 newPos++;
2820 }
2821 }
2822 if (newPos != methods.length) {
2823 methods = Arrays.copyOf(methods, newPos);
2824 }
2825 }
2826
2827 /* Removes all Methods from this MethodArray that have a more specific
2828 * default Method in this MethodArray.
2829 *
2830 * Users of MethodArray are responsible for pruning Methods that have
2831 * a more specific <em>concrete</em> Method.
2832 */
2833 void removeLessSpecifics() {
2834 if (!hasDefaults())
2835 return;
2836
2837 for (int i = 0; i < length; i++) {
2838 Method m = get(i);
2839 if (m == null || !m.isDefault())
2840 continue;
2841
2842 for (int j = 0; j < length; j++) {
2843 if (i == j)
2844 continue;
2845
2846 Method candidate = get(j);
2847 if (candidate == null)
2848 continue;
2849
2850 if (!matchesNameAndDescriptor(m, candidate))
2851 continue;
2852
2853 if (hasMoreSpecificClass(m, candidate))
2854 remove(j);
2855 }
2856 }
2857 }
2858
2859 Method[] getArray() {
2860 return methods;
2861 }
2862
2863 // Returns true if m1 is more specific than m2
2864 static boolean hasMoreSpecificClass(Method m1, Method m2) {
2865 Class<?> m1Class = m1.getDeclaringClass();
2866 Class<?> m2Class = m2.getDeclaringClass();
2867 return m1Class != m2Class && m2Class.isAssignableFrom(m1Class);
2868 }
2869 }
2870
2871
2872 // Returns an array of "root" methods. These Method objects must NOT
2873 // be propagated to the outside world, but must instead be copied
2874 // via ReflectionFactory.copyMethod.
2875 private Method[] privateGetPublicMethods() {
2876 checkInitted();
2877 Method[] res;
2878 ReflectionData<T> rd = reflectionData();
2879 if (rd != null) {
2880 res = rd.publicMethods;
2881 if (res != null) return res;
2882 }
2883
2884 // No cached value available; compute value recursively.
2885 // Start by fetching public declared methods
2886 MethodArray methods = new MethodArray();
2887 {
2888 Method[] tmp = privateGetDeclaredMethods(true);
2889 methods.addAll(tmp);
2890 }
2891 // Now recur over superclass and direct superinterfaces.
2892 // Go over superinterfaces first so we can more easily filter
2893 // out concrete implementations inherited from superclasses at
2894 // the end.
2895 MethodArray inheritedMethods = new MethodArray();
2896 for (Class<?> i : getInterfaces()) {
2897 inheritedMethods.addInterfaceMethods(i.privateGetPublicMethods());
2898 }
2899 if (!isInterface()) {
2900 Class<?> c = getSuperclass();
2901 if (c != null) {
2902 MethodArray supers = new MethodArray();
2903 supers.addAll(c.privateGetPublicMethods());
2904 // Filter out concrete implementations of any
2905 // interface methods
2906 for (int i = 0; i < supers.length(); i++) {
2907 Method m = supers.get(i);
2908 if (m != null &&
2909 !Modifier.isAbstract(m.getModifiers()) &&
2910 !m.isDefault()) {
2911 inheritedMethods.removeByNameAndDescriptor(m);
2912 }
2913 }
2914 // Insert superclass's inherited methods before
2915 // superinterfaces' to satisfy getMethod's search
2916 // order
2917 supers.addAll(inheritedMethods);
2918 inheritedMethods = supers;
2919 }
2920 }
2921 // Filter out all local methods from inherited ones
2922 for (int i = 0; i < methods.length(); i++) {
2923 Method m = methods.get(i);
2924 inheritedMethods.removeByNameAndDescriptor(m);
2925 }
2926 methods.addAllIfNotPresent(inheritedMethods);
2927 methods.removeLessSpecifics();
2928 methods.compactAndTrim();
2929 res = methods.getArray();
2930 if (rd != null) {
2931 rd.publicMethods = res;
2932 }
2933 return res;
2934 }
2935
2936
2937 //
2938 // Helpers for fetchers of one field, method, or constructor
2939 //
2940
2941 private static Field searchFields(Field[] fields, String name) {
2942 String internedName = name.intern();
2943 for (Field field : fields) {
2944 if (field.getName() == internedName) {
2945 return getReflectionFactory().copyField(field);
2946 }
2947 }
2980 return null;
2981 }
2982
2983 private static Method searchMethods(Method[] methods,
2984 String name,
2985 Class<?>[] parameterTypes)
2986 {
2987 Method res = null;
2988 String internedName = name.intern();
2989 for (Method m : methods) {
2990 if (m.getName() == internedName
2991 && arrayContentsEq(parameterTypes, m.getParameterTypes())
2992 && (res == null
2993 || res.getReturnType().isAssignableFrom(m.getReturnType())))
2994 res = m;
2995 }
2996
2997 return (res == null ? res : getReflectionFactory().copyMethod(res));
2998 }
2999
3000 private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
3001 MethodArray interfaceCandidates = new MethodArray(2);
3002 Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates);
3003 if (res != null)
3004 return res;
3005
3006 // Not found on class or superclass directly
3007 interfaceCandidates.removeLessSpecifics();
3008 return interfaceCandidates.getFirst(); // may be null
3009 }
3010
3011 private Method privateGetMethodRecursive(String name,
3012 Class<?>[] parameterTypes,
3013 boolean includeStaticMethods,
3014 MethodArray allInterfaceCandidates) {
3015 // Note: the intent is that the search algorithm this routine
3016 // uses be equivalent to the ordering imposed by
3017 // privateGetPublicMethods(). It fetches only the declared
3018 // public methods for each class, however, to reduce the
3019 // number of Method objects which have to be created for the
3020 // common case where the method being requested is declared in
3021 // the class which is being queried.
3022 //
3023 // Due to default methods, unless a method is found on a superclass,
3024 // methods declared in any superinterface needs to be considered.
3025 // Collect all candidates declared in superinterfaces in {@code
3026 // allInterfaceCandidates} and select the most specific if no match on
3027 // a superclass is found.
3028
3029 // Must _not_ return root methods
3030 Method res;
3031 // Search declared public methods
3032 if ((res = searchMethods(privateGetDeclaredMethods(true),
3033 name,
3034 parameterTypes)) != null) {
3035 if (includeStaticMethods || !Modifier.isStatic(res.getModifiers()))
3036 return res;
3037 }
3038 // Search superclass's methods
3039 if (!isInterface()) {
3040 Class<? super T> c = getSuperclass();
3041 if (c != null) {
3042 if ((res = c.getMethod0(name, parameterTypes, true)) != null) {
3043 return res;
3044 }
3045 }
3046 }
3047 // Search superinterfaces' methods
3048 Class<?>[] interfaces = getInterfaces();
3049 for (Class<?> c : interfaces)
3050 if ((res = c.getMethod0(name, parameterTypes, false)) != null)
3051 allInterfaceCandidates.add(res);
3052 // Not found
3053 return null;
3054 }
3055
3056 private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
3057 int which) throws NoSuchMethodException
3058 {
3059 Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
3060 for (Constructor<T> constructor : constructors) {
3061 if (arrayContentsEq(parameterTypes,
3062 constructor.getParameterTypes())) {
3063 return getReflectionFactory().copyConstructor(constructor);
3064 }
3065 }
3066 throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
3067 }
3068
3069 //
3070 // Other helpers and base implementation
3071 //
|