changeset 10281:67a7e08198c7

8055063: Parameter#toString() fails w/ AIOOBE for ctr of inner class w/ generic type Summary: Add getAllGenericParameters, which attempts to report generic parameters with synthetic parameters to the best extent possible with current classfile information. Reviewed-by: jfranck
author emc
date Tue, 18 Nov 2014 12:36:41 -0500
parents e51840480603
children 736dc97f9db5
files src/share/classes/java/lang/reflect/Executable.java src/share/classes/java/lang/reflect/Parameter.java
diffstat 2 files changed, 49 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/reflect/Executable.java	Tue Nov 18 17:50:08 2014 +0400
+++ b/src/share/classes/java/lang/reflect/Executable.java	Tue Nov 18 12:36:41 2014 -0500
@@ -287,6 +287,53 @@
     }
 
     /**
+     * Behaves like {@code getGenericParameterTypes}, but returns type
+     * information for all parameters, including synthetic parameters.
+     */
+    Type[] getAllGenericParameterTypes() {
+        final boolean genericInfo = hasGenericInformation();
+
+        // Easy case: we don't have generic parameter information.  In
+        // this case, we just return the result of
+        // getParameterTypes().
+        if (!genericInfo) {
+            return getParameterTypes();
+        } else {
+            final boolean realParamData = hasRealParameterData();
+            final Type[] genericParamTypes = getGenericParameterTypes();
+            final Type[] nonGenericParamTypes = getParameterTypes();
+            final Type[] out = new Type[nonGenericParamTypes.length];
+            final Parameter[] params = getParameters();
+            int fromidx = 0;
+            // If we have real parameter data, then we use the
+            // synthetic and mandate flags to our advantage.
+            if (realParamData) {
+                for (int i = 0; i < out.length; i++) {
+                    final Parameter param = params[i];
+                    if (param.isSynthetic() || param.isImplicit()) {
+                        // If we hit a synthetic or mandated parameter,
+                        // use the non generic parameter info.
+                        out[i] = nonGenericParamTypes[i];
+                    } else {
+                        // Otherwise, use the generic parameter info.
+                        out[i] = genericParamTypes[fromidx];
+                        fromidx++;
+                    }
+                }
+            } else {
+                // Otherwise, use the non-generic parameter data.
+                // Without method parameter reflection data, we have
+                // no way to figure out which parameters are
+                // synthetic/mandated, thus, no way to match up the
+                // indexes.
+                return genericParamTypes.length == nonGenericParamTypes.length ?
+                    genericParamTypes : nonGenericParamTypes;
+            }
+            return out;
+        }
+    }
+
+    /**
      * Returns an array of {@code Parameter} objects that represent
      * all the parameters to the underlying executable represented by
      * this object.  Returns an array of length 0 if the executable
@@ -654,7 +701,7 @@
                         getConstantPool(getDeclaringClass()),
                 this,
                 getDeclaringClass(),
-                getGenericParameterTypes(),
+                getAllGenericParameterTypes(),
                 TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER);
     }
 
--- a/src/share/classes/java/lang/reflect/Parameter.java	Tue Nov 18 17:50:08 2014 +0400
+++ b/src/share/classes/java/lang/reflect/Parameter.java	Tue Nov 18 12:36:41 2014 -0500
@@ -198,7 +198,7 @@
     public Type getParameterizedType() {
         Type tmp = parameterTypeCache;
         if (null == tmp) {
-            tmp = executable.getGenericParameterTypes()[index];
+            tmp = executable.getAllGenericParameterTypes()[index];
             parameterTypeCache = tmp;
         }