8004729: Add java.lang.reflect.Parameter and related changes for parameter reflection
authorrobm
Wed, 23 Jan 2013 17:54:34 +0000
changeset 15294 df55735ea03c
parent 15293 42e74ff49a50
child 15296 e652ed68b1c4
8004729: Add java.lang.reflect.Parameter and related changes for parameter reflection Reviewed-by: darcy, forax, psandoz, dholmes, tbell
jdk/make/java/java/Exportedfiles.gmk
jdk/make/java/java/FILES_c.gmk
jdk/make/java/java/mapfile-vers
jdk/makefiles/mapfiles/libjava/mapfile-vers
jdk/src/share/classes/java/lang/reflect/Constructor.java
jdk/src/share/classes/java/lang/reflect/Executable.java
jdk/src/share/classes/java/lang/reflect/Method.java
jdk/src/share/classes/java/lang/reflect/Modifier.java
jdk/src/share/classes/java/lang/reflect/Parameter.java
jdk/src/share/javavm/export/jvm.h
jdk/src/share/native/java/lang/reflect/Executable.c
jdk/test/java/lang/reflect/Parameter/WithParameters.java
jdk/test/java/lang/reflect/Parameter/WithoutParameters.java
--- a/jdk/make/java/java/Exportedfiles.gmk	Wed Jan 23 15:12:28 2013 +0000
+++ b/jdk/make/java/java/Exportedfiles.gmk	Wed Jan 23 17:54:34 2013 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,7 @@
     java/lang/reflect/Constructor.java \
     java/lang/reflect/InvocationTargetException.java \
     java/lang/reflect/Array.java \
+    java/lang/reflect/Executable.java \
     java/lang/reflect/Proxy.java \
     java/security/AccessController.java \
     java/util/Date.java \
@@ -129,6 +130,7 @@
     java/lang/reflect/Constructor.java \
     java/lang/reflect/InvocationTargetException.java \
     java/lang/reflect/Array.java \
+    java/lang/reflect/Executable.java \
     java/lang/reflect/Proxy.java \
     java/lang/ref/Reference.java \
     java/lang/ref/Finalizer.java \
--- a/jdk/make/java/java/FILES_c.gmk	Wed Jan 23 15:12:28 2013 +0000
+++ b/jdk/make/java/java/FILES_c.gmk	Wed Jan 23 17:54:34 2013 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 	Compiler.c \
 	Console_md.c \
 	Double.c \
+	Executable.c \
 	FileDescriptor_md.c \
 	FileInputStream.c \
 	FileInputStream_md.c \
--- a/jdk/make/java/java/mapfile-vers	Wed Jan 23 15:12:28 2013 +0000
+++ b/jdk/make/java/java/mapfile-vers	Wed Jan 23 17:54:34 2013 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -189,6 +189,7 @@
 		Java_java_lang_reflect_Array_setInt;
 		Java_java_lang_reflect_Array_setLong;
 		Java_java_lang_reflect_Array_setShort;
+		Java_java_lang_reflect_Executable_getParameters0;
 		Java_java_lang_Runtime_freeMemory;
                 Java_java_lang_Runtime_maxMemory;
 		Java_java_lang_Runtime_gc;
--- a/jdk/makefiles/mapfiles/libjava/mapfile-vers	Wed Jan 23 15:12:28 2013 +0000
+++ b/jdk/makefiles/mapfiles/libjava/mapfile-vers	Wed Jan 23 17:54:34 2013 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -189,6 +189,7 @@
 		Java_java_lang_reflect_Array_setInt;
 		Java_java_lang_reflect_Array_setLong;
 		Java_java_lang_reflect_Array_setShort;
+		Java_java_lang_reflect_Executable_getParameters0;
 		Java_java_lang_Runtime_freeMemory;
                 Java_java_lang_Runtime_maxMemory;
 		Java_java_lang_Runtime_gc;
--- a/jdk/src/share/classes/java/lang/reflect/Constructor.java	Wed Jan 23 15:12:28 2013 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/Constructor.java	Wed Jan 23 17:54:34 2013 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -205,6 +205,11 @@
 
     /**
      * {@inheritDoc}
+     */
+    public int getParameterCount() { return parameterTypes.length; }
+
+    /**
+     * {@inheritDoc}
      * @throws GenericSignatureFormatError {@inheritDoc}
      * @throws TypeNotPresentException {@inheritDoc}
      * @throws MalformedParameterizedTypeException {@inheritDoc}
--- a/jdk/src/share/classes/java/lang/reflect/Executable.java	Wed Jan 23 15:12:28 2013 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/Executable.java	Wed Jan 23 17:54:34 2013 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -226,6 +226,18 @@
     public abstract Class<?>[] getParameterTypes();
 
     /**
+     * Returns the number of formal parameters (including any
+     * synthetic or synthesized parameters) for the executable
+     * represented by this object.
+     *
+     * @return The number of formal parameters for the executable this
+     * object represents
+     */
+    public int getParameterCount() {
+        throw new AbstractMethodError();
+    }
+
+    /**
      * Returns an array of {@code Type} objects that represent the formal
      * parameter types, in declaration order, of the executable represented by
      * this object. Returns an array of length 0 if the
@@ -259,6 +271,60 @@
     }
 
     /**
+     * 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
+     * has no parameters.
+     *
+     * @return an array of {@code Parameter} objects representing all
+     * the parameters to the executable this object represents
+     */
+    public Parameter[] getParameters() {
+        // TODO: This may eventually need to be guarded by security
+        // mechanisms similar to those in Field, Method, etc.
+        //
+        // Need to copy the cached array to prevent users from messing
+        // with it.  Since parameters are immutable, we can
+        // shallow-copy.
+        return privateGetParameters().clone();
+    }
+
+    private Parameter[] synthesizeAllParams() {
+        final int realparams = getParameterCount();
+        final Parameter[] out = new Parameter[realparams];
+        for (int i = 0; i < realparams; i++)
+            // TODO: is there a way to synthetically derive the
+            // modifiers?  Probably not in the general case, since
+            // we'd have no way of knowing about them, but there
+            // may be specific cases.
+            out[i] = new Parameter("arg" + i, 0, this, i);
+        return out;
+    }
+
+    private Parameter[] privateGetParameters() {
+        // Use tmp to avoid multiple writes to a volatile.
+        Parameter[] tmp = parameters;
+
+        if (tmp == null) {
+
+            // Otherwise, go to the JVM to get them
+            tmp = getParameters0();
+
+            // If we get back nothing, then synthesize parameters
+            if (tmp == null)
+                tmp = synthesizeAllParams();
+
+            parameters = tmp;
+        }
+
+        return tmp;
+    }
+
+    private transient volatile Parameter[] parameters;
+
+    private native Parameter[] getParameters0();
+
+    /**
      * Returns an array of {@code Class} objects that represent the
      * types of exceptions declared to be thrown by the underlying
      * executable represented by this object.  Returns an array of
@@ -403,4 +469,5 @@
         }
         return declaredAnnotations;
     }
+
 }
--- a/jdk/src/share/classes/java/lang/reflect/Method.java	Wed Jan 23 15:12:28 2013 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/Method.java	Wed Jan 23 17:54:34 2013 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -255,6 +255,12 @@
 
     /**
      * {@inheritDoc}
+     */
+    public int getParameterCount() { return parameterTypes.length; }
+
+
+    /**
+     * {@inheritDoc}
      * @throws GenericSignatureFormatError {@inheritDoc}
      * @throws TypeNotPresentException {@inheritDoc}
      * @throws MalformedParameterizedTypeException {@inheritDoc}
--- a/jdk/src/share/classes/java/lang/reflect/Modifier.java	Wed Jan 23 15:12:28 2013 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/Modifier.java	Wed Jan 23 17:54:34 2013 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -340,12 +340,17 @@
     static final int BRIDGE    = 0x00000040;
     static final int VARARGS   = 0x00000080;
     static final int SYNTHETIC = 0x00001000;
-    static final int ANNOTATION= 0x00002000;
+    static final int ANNOTATION  = 0x00002000;
     static final int ENUM      = 0x00004000;
+    static final int SYNTHESIZED = 0x00010000;
     static boolean isSynthetic(int mod) {
       return (mod & SYNTHETIC) != 0;
     }
 
+    static boolean isSynthesized(int mod) {
+      return (mod & SYNTHESIZED) != 0;
+    }
+
     /**
      * See JLSv3 section 8.1.1.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java	Wed Jan 23 17:54:34 2013 +0000
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.reflect;
+
+import java.lang.annotation.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import sun.reflect.annotation.AnnotationSupport;
+
+/**
+ * Information about method parameters.
+ *
+ * A {@code Parameter} provides information about method parameters,
+ * including its name and modifiers.  It also provides an alternate
+ * means of obtaining attributes for the parameter.
+ *
+ * @since 1.8
+ */
+public final class Parameter implements AnnotatedElement {
+
+    private final String name;
+    private final int modifiers;
+    private final Executable executable;
+    private int index;
+
+    /**
+     * Package-private constructor for {@code Parameter}.
+     *
+     * If method parameter data is present in the classfile, then the
+     * JVM creates {@code Parameter} objects directly.  If it is
+     * absent, however, then {@code Executable} uses this constructor
+     * to synthesize them.
+     *
+     * @param name The name of the parameter.
+     * @param modifiers The modifier flags for the parameter.
+     * @param executable The executable which defines this parameter.
+     * @param index The index of the parameter.
+     */
+    Parameter(String name,
+              int modifiers,
+              Executable executable,
+              int index) {
+        this.name = name;
+        this.modifiers = modifiers;
+        this.executable = executable;
+        this.index = index;
+    }
+
+    /**
+     * Compares based on the executable and the index.
+     *
+     * @param obj The object to compare.
+     * @return Whether or not this is equal to the argument.
+     */
+    public boolean equals(Object obj) {
+        if(obj instanceof Parameter) {
+            Parameter other = (Parameter)obj;
+            return (other.executable.equals(executable) &&
+                    other.index == index);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash code based on the executable's hash code and the
+     * index.
+     *
+     * @return A hash code based on the executable's hash code.
+     */
+    public int hashCode() {
+        return executable.hashCode() ^ index;
+    }
+
+    /**
+     * Returns a string representation of the parameter's modifiers,
+     * its attributes, its type, its name, and a trailing ... if it is
+     * a variadic parameter.
+     *
+     * @return A string representation of the parameter and associated
+     * information.
+     */
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        final Type type = getParameterizedType();
+        final String typename = (type instanceof Class)?
+            Field.getTypeName((Class)type):
+            (type.toString());
+
+        sb.append(Modifier.toString(getModifiers()));
+        sb.append(" ");
+
+        if(isVarArgs())
+            sb.append(typename.replaceFirst("\\[\\]$", "..."));
+        else
+            sb.append(typename);
+
+        sb.append(" ");
+        sb.append(name);
+
+        return sb.toString();
+    }
+
+    /**
+     * Return the {@code Executable} which declares this parameter.
+     *
+     * @return The {@code Executable} declaring this parameter.
+     */
+    public Executable getDeclaringExecutable() {
+        return executable;
+    }
+
+    /**
+     * Get the modifier flags for this the parameter represented by
+     * this {@code Parameter} object.
+     *
+     * @return The modifier flags for this parameter.
+     */
+    public int getModifiers() {
+        return modifiers;
+    }
+
+    /**
+     * Returns the name of the parameter represented by this
+     * {@code Parameter} object.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns a {@code Type} object that identifies the parameterized
+     * type for the parameter represented by this {@code Parameter}
+     * object.
+     *
+     * @return a {@code Type} object identifying the parameterized
+     * type of the parameter represented by this object
+     */
+    public Type getParameterizedType() {
+        Type tmp = parameterTypeCache;
+        if (null == tmp) {
+            tmp = executable.getGenericParameterTypes()[index];
+            parameterTypeCache = tmp;
+        }
+
+        return tmp;
+    }
+
+    private transient volatile Type parameterTypeCache = null;
+
+    /**
+     * Returns a {@code Class} object that identifies the
+     * declared type for the parameter represented by this
+     * {@code Parameter} object.
+     *
+     * @return a {@code Class} object identifying the declared
+     * type of the parameter represented by this object
+     */
+    public Class<?> getType() {
+        Class<?> tmp = parameterClassCache;
+        if (null == tmp) {
+            tmp = executable.getParameterTypes()[index];
+            parameterClassCache = tmp;
+        }
+        return tmp;
+    }
+
+    private transient volatile Class<?> parameterClassCache = null;
+
+    /**
+     * Returns {@code true} if this parameter is a synthesized
+     * construct; returns {@code false} otherwise.
+     *
+     * @return true if and only if this parameter is a synthesized
+     * construct as defined by
+     * <cite>The Java&trade; Language Specification</cite>.
+     */
+    public boolean isSynthesized() {
+        return Modifier.isSynthesized(getModifiers());
+    }
+
+    /**
+     * Returns {@code true} if this parameter is a synthetic
+     * construct; returns {@code false} otherwise.
+     *
+     * @jls 13.1 The Form of a Binary
+     * @return true if and only if this parameter is a synthetic
+     * construct as defined by
+     * <cite>The Java&trade; Language Specification</cite>.
+     */
+    public boolean isSynthetic() {
+        return Modifier.isSynthetic(getModifiers());
+    }
+
+    /**
+     * Returns {@code true} if this parameter represents a variable
+     * argument list; returns {@code false} otherwise.
+     *
+     * @return {@code true} if an only if this parameter represents a
+     * variable argument list.
+     */
+    public boolean isVarArgs() {
+        return executable.isVarArgs() &&
+            index == executable.getParameterCount() - 1;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+
+        return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+
+        return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Annotation[] getDeclaredAnnotations() {
+        return executable.getParameterAnnotations()[index];
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
+        // Only annotations on classes are inherited, for all other
+        // objects getDeclaredAnnotation is the same as
+        // getAnnotation.
+        return getAnnotation(annotationClass);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
+        // Only annotations on classes are inherited, for all other
+        // objects getDeclaredAnnotations is the same as
+        // getAnnotations.
+        return getAnnotations(annotationClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Annotation[] getAnnotations() {
+        return getDeclaredAnnotations();
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean isAnnotationPresent(
+        Class<? extends Annotation> annotationClass) {
+        return getAnnotation(annotationClass) != null;
+    }
+
+    private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
+
+    private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
+        if(null == declaredAnnotations) {
+            declaredAnnotations =
+                new HashMap<Class<? extends Annotation>, Annotation>();
+            Annotation[] ann = getDeclaredAnnotations();
+            for(int i = 0; i < ann.length; i++)
+                declaredAnnotations.put(ann[i].annotationType(), ann[i]);
+        }
+        return declaredAnnotations;
+    }
+
+}
--- a/jdk/src/share/javavm/export/jvm.h	Wed Jan 23 15:12:28 2013 +0000
+++ b/jdk/src/share/javavm/export/jvm.h	Wed Jan 23 17:54:34 2013 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -553,6 +553,13 @@
 (JNIEnv *env, jobject unused, jobject jcpool, jint index);
 
 /*
+ * Parameter reflection
+ */
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetMethodParameters(JNIEnv *env, jobject method);
+
+/*
  * java.security.*
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/java/lang/reflect/Executable.c	Wed Jan 23 17:54:34 2013 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "java_lang_reflect_Executable.h"
+
+JNIEXPORT jobject JNICALL
+Java_java_lang_reflect_Executable_getParameters0(JNIEnv *env,
+                                                 jobject method) {
+  return JVM_GetMethodParameters(env, method);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Parameter/WithParameters.java	Wed Jan 23 17:54:34 2013 +0000
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @ignore
+ * @test
+ * @compile -parameters WithParameters.java
+ * @run main WithParameters
+ * @summary javac should generate method parameters correctly.
+ */
+
+import java.lang.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.List;
+
+public class WithParameters {
+
+    private static final Class<?>[] qux_types = {
+        int.class, Foo.class, List.class, List.class, List.class, String[].class
+    };
+
+    private static final String[] qux_names = {
+        "quux", "quuux", "l", "l2", "l3", "rest"
+    };
+
+    public static void main(String argv[]) throws Exception {
+        int error = 0;
+        Method[] methods = Foo.class.getMethods();
+        for(Method m : methods) {
+            System.err.println("Inspecting method " + m.getName());
+            Parameter[] parameters = m.getParameters();
+            if(parameters == null)
+                throw new Exception("getParameters should never be null");
+            for(int i = 0; i < parameters.length; i++) {
+                    Parameter p = parameters[i];
+                    if(!p.getDeclaringExecutable().equals(m)) {
+                        System.err.println(p + ".getDeclaringExecutable != " + m);
+                        error++;
+                    }
+                    if(null == p.getType()) {
+                        System.err.println(p + ".getType() == null");
+                        error++;
+                    }
+                    if(null == p.getParameterizedType()) {
+                        System.err.println(p + ".getParameterizedType == null");
+                        error++;
+                    }
+            }
+            if(m.getName().equals("qux")) {
+                if(6 != parameters.length) {
+                    System.err.println("Wrong number of parameters for qux");
+                    error++;
+                }
+                for(int i = 0; i < parameters.length; i++) {
+                    Parameter p = parameters[i];
+                    if(!parameters[i].getName().equals(qux_names[i])) {
+                        System.err.println("Wrong parameter name for " + parameters[i]);
+                        error++;
+                    }
+                    // The getType family work with or without
+                    // parameter attributes compiled in.
+                    if(!parameters[i].getType().equals(qux_types[i])) {
+                        System.err.println("Wrong parameter type for " + parameters[0] + ": expected " + qux_types[i] + ", but got " + parameters[i].getType());
+                        error++;
+                    }
+                }
+                if(parameters[0].toString().equals("int quux")) {
+                    System.err.println("toString for quux is wrong");
+                    error++;
+                }
+                if(parameters[0].getModifiers() != Modifier.FINAL) {
+                    System.err.println("quux is not final");
+                    error++;
+                }
+                if(parameters[0].isVarArgs()) {
+                    System.err.println("isVarArg for quux is wrong");
+                    error++;
+                }
+                if(!parameters[0].getParameterizedType().equals(int.class)) {
+                    System.err.println("getParameterizedType for quux is wrong");
+                    error++;
+                }
+                if(parameters[1].toString().equals("WithParameters$Foo quuux")) {
+                    System.err.println("toString for quuux is wrong");
+                    error++;
+                }
+                if(parameters[1].isVarArgs()) {
+                    System.err.println("isVarArg for quuux is wrong");
+                    error++;
+                }
+                if(!parameters[1].getParameterizedType().equals(Foo.class)) {
+                    System.err.println("getParameterizedType for quuux is wrong");
+                    error++;
+                }
+                Annotation[] anns = parameters[1].getAnnotations();
+                if(1 != anns.length) {
+                    System.err.println("getAnnotations missed an annotation");
+                    error++;
+                } else if(!anns[0].annotationType().equals(Thing.class)) {
+                    System.err.println("getAnnotations has the wrong annotation");
+                    error++;
+                }
+                if(parameters[2].toString().equals("java.util.List<?> quuux")) {
+                    System.err.println("toString for l is wrong");
+                    error++;
+                }
+                if(parameters[2].isVarArgs()) {
+                    System.err.println("isVarArg for l is wrong");
+                    error++;
+                }
+                if(!(parameters[2].getParameterizedType() instanceof
+                     ParameterizedType)) {
+                    System.err.println("getParameterizedType for l is wrong");
+                    error++;
+                } else {
+                    ParameterizedType pt =
+                        (ParameterizedType) parameters[2].getParameterizedType();
+                    if(!pt.getRawType().equals(List.class)) {
+                        System.err.println("Raw type for l is wrong");
+                        error++;
+                    }
+                    if(1 != pt.getActualTypeArguments().length) {
+                        System.err.println("Number of type parameters for l is wrong");
+                        error++;
+                    }
+                    if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) {
+                        System.err.println("Type parameter for l is wrong");
+                        error++;
+                    }
+                }
+                if(parameters[3].toString().equals("java.util.List<WithParameters$Foo> l")) {
+                    System.err.println("toString for l2 is wrong");
+                    error++;
+                }
+                if(parameters[3].isVarArgs()) {
+                    System.err.println("isVarArg for l2 is wrong");
+                    error++;
+                }
+                if(!(parameters[3].getParameterizedType() instanceof
+                     ParameterizedType)) {
+                    System.err.println("getParameterizedType for l2 is wrong");
+                    error++;
+                } else {
+                    ParameterizedType pt =
+                        (ParameterizedType) parameters[3].getParameterizedType();
+                    if(!pt.getRawType().equals(List.class)) {
+                        System.err.println("Raw type for l2 is wrong");
+                        error++;
+                    }
+                    if(1 != pt.getActualTypeArguments().length) {
+                        System.err.println("Number of type parameters for l2 is wrong");
+                        error++;
+                    }
+                    if(!(pt.getActualTypeArguments()[0].equals(Foo.class))) {
+                        System.err.println("Type parameter for l2 is wrong");
+                        error++;
+                    }
+                }
+                if(parameters[4].toString().equals("java.util.List<? extends WithParameters$Foo> l")) {
+                    System.err.println("toString for l3 is wrong");
+                    error++;
+                }
+                if(parameters[4].isVarArgs()) {
+                    System.err.println("isVarArg for l3 is wrong");
+                    error++;
+                }
+                if(!(parameters[4].getParameterizedType() instanceof
+                     ParameterizedType)) {
+                    System.err.println("getParameterizedType for l3 is wrong");
+                    error++;
+                } else {
+                    ParameterizedType pt =
+                        (ParameterizedType) parameters[4].getParameterizedType();
+                    if(!pt.getRawType().equals(List.class)) {
+                        System.err.println("Raw type for l3 is wrong");
+                        error++;
+                    }
+                    if(1 != pt.getActualTypeArguments().length) {
+                        System.err.println("Number of type parameters for l3 is wrong");
+                        error++;
+                    }
+                    if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) {
+                        System.err.println("Type parameter for l3 is wrong");
+                        error++;
+                    } else {
+                        WildcardType wt = (WildcardType)
+                            pt.getActualTypeArguments()[0];
+                        if(!wt.getUpperBounds()[0].equals(Foo.class)) {
+                            System.err.println("Upper bounds on type parameter fol l3 is wrong");
+                            error++;
+                        }
+                    }
+                }
+                if(parameters[5].toString().equals("java.lang.String... rest")) {
+                    System.err.println("toString for l is wrong");
+                    error++;
+                }
+                if(!parameters[5].isVarArgs()) {
+                    System.err.println("isVarArg for rest is wrong");
+                    error++;
+                }
+                if(!(parameters[5].getParameterizedType().equals(String[].class))) {
+                    System.err.println("getParameterizedType for rest is wrong");
+                    error++;
+                }
+            }
+        }
+        if(0 != error)
+            throw new Exception("Failed " + error + " tests");
+    }
+
+    void test(int test) {}
+
+    public class Foo {
+        int thing;
+        public void qux(final int quux, @Thing Foo quuux,
+                        List<?> l, List<Foo> l2,
+                        List<? extends Foo> l3,
+                        String... rest) {}
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface Thing {}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java	Wed Jan 23 17:54:34 2013 +0000
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary javac should generate method parameters correctly.
+ */
+
+import java.lang.*;
+import java.lang.reflect.*;
+import java.util.List;
+
+public class WithoutParameters {
+
+    private static final Class<?>[] qux_types = {
+        int.class,
+        Foo.class,
+        List.class,
+        List.class,
+        List.class,
+        String[].class
+    };
+
+    public static void main(String argv[]) throws Exception {
+        int error = 0;
+        Method[] methods = Foo.class.getMethods();
+        for(Method m : methods) {
+            System.err.println("Inspecting method " + m);
+            Parameter[] parameters = m.getParameters();
+            if(parameters == null)
+                throw new Exception("getParameters should never be null");
+            for(int i = 0; i < parameters.length; i++) {
+                    Parameter p = parameters[i];
+                    if(!p.getDeclaringExecutable().equals(m)) {
+                        System.err.println(p + ".getDeclaringExecutable != " + m);
+                        error++;
+                    }
+                    if(null == p.getType()) {
+                        System.err.println(p + ".getType() == null");
+                        error++;
+                    }
+                    if(null == p.getParameterizedType()) {
+                        System.err.println(p + ".getParameterizedType == null");
+                        error++;
+                    }
+            }
+            if(m.getName().equals("qux")) {
+                if(6 != parameters.length) {
+                    System.err.println("Wrong number of parameters for qux");
+                    error++;
+                }
+                for(int i = 0; i < parameters.length; i++) {
+                    Parameter p = parameters[i];
+                    // The getType family work with or without
+                    // parameter attributes compiled in.
+                    if(!parameters[i].getType().equals(qux_types[i])) {
+                        System.err.println("Wrong parameter type for " + parameters[0] + ": expected " + qux_types[i] + ", but got " + parameters[i].getType());
+                        error++;
+                    }
+                }
+                if(!parameters[0].getParameterizedType().equals(int.class)) {
+                    System.err.println("getParameterizedType for quux is wrong");
+                    error++;
+                }
+                if(!parameters[1].getParameterizedType().equals(Foo.class)) {
+                    System.err.println("getParameterizedType for quux is wrong");
+                    error++;
+                }
+                if(!(parameters[2].getParameterizedType() instanceof
+                     ParameterizedType)) {
+                    System.err.println("getParameterizedType for l is wrong");
+                    error++;
+                } else {
+                    ParameterizedType pt =
+                        (ParameterizedType) parameters[2].getParameterizedType();
+                    if(!pt.getRawType().equals(List.class)) {
+                        System.err.println("Raw type for l is wrong");
+                        error++;
+                    }
+                    if(1 != pt.getActualTypeArguments().length) {
+                        System.err.println("Number of type parameters for l is wrong");
+                        error++;
+                    }
+                    if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) {
+                        System.err.println("Type parameter for l is wrong");
+                        error++;
+                    }
+                }
+                if(!(parameters[3].getParameterizedType() instanceof
+                     ParameterizedType)) {
+                    System.err.println("getParameterizedType for l2 is wrong");
+                    error++;
+                } else {
+                    ParameterizedType pt =
+                        (ParameterizedType) parameters[3].getParameterizedType();
+                    if(!pt.getRawType().equals(List.class)) {
+                        System.err.println("Raw type for l2 is wrong");
+                        error++;
+                    }
+                    if(1 != pt.getActualTypeArguments().length) {
+                        System.err.println("Number of type parameters for l2 is wrong");
+                        error++;
+                    }
+                    if(!(pt.getActualTypeArguments()[0].equals(Foo.class))) {
+                        System.err.println("Type parameter for l2 is wrong");
+                        error++;
+                    }
+                }
+                if(!(parameters[4].getParameterizedType() instanceof
+                     ParameterizedType)) {
+                    System.err.println("getParameterizedType for l3 is wrong");
+                    error++;
+                } else {
+                    ParameterizedType pt =
+                        (ParameterizedType) parameters[4].getParameterizedType();
+                    if(!pt.getRawType().equals(List.class)) {
+                        System.err.println("Raw type for l3 is wrong");
+                        error++;
+                    }
+                    if(1 != pt.getActualTypeArguments().length) {
+                        System.err.println("Number of type parameters for l3 is wrong");
+                        error++;
+                    }
+                    if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) {
+                        System.err.println("Type parameter for l3 is wrong");
+                        error++;
+                    } else {
+                        WildcardType wt = (WildcardType)
+                            pt.getActualTypeArguments()[0];
+                        if(!wt.getUpperBounds()[0].equals(Foo.class)) {
+                            System.err.println("Upper bounds on type parameter fol l3 is wrong");
+                            error++;
+                        }
+                    }
+                }
+                if(!parameters[5].isVarArgs()) {
+                    System.err.println("isVarArg for rest is wrong");
+                    error++;
+                }
+                if(!(parameters[5].getParameterizedType().equals(String[].class))) {
+                    System.err.println("getParameterizedType for rest is wrong");
+                    error++;
+                }
+
+            }
+        }
+        if(0 != error)
+            throw new Exception("Failed " + error + " tests");
+    }
+
+    public class Foo {
+        int thing;
+        public void qux(int quux, Foo quuux,
+                        List<?> l, List<Foo> l2,
+                        List<? extends Foo> l3,
+                        String... rest) {}
+        public class Inner {
+            int thang;
+            public Inner(int theng) {
+                thang = theng + thing;
+            }
+        }
+    }
+
+}