--- old/make/java/java/Exportedfiles.gmk 2013-01-17 16:14:32.336603516 -0500 +++ new/make/java/java/Exportedfiles.gmk 2013-01-17 16:14:32.108601150 -0500 @@ -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 \ --- old/make/java/java/FILES_c.gmk 2013-01-17 16:14:32.930609672 -0500 +++ new/make/java/java/FILES_c.gmk 2013-01-17 16:14:32.699607275 -0500 @@ -32,6 +32,7 @@ Compiler.c \ Console_md.c \ Double.c \ + Executable.c \ FileDescriptor_md.c \ FileInputStream.c \ FileInputStream_md.c \ --- old/make/java/java/mapfile-vers 2013-01-17 16:14:33.536615938 -0500 +++ new/make/java/java/mapfile-vers 2013-01-17 16:14:33.307613564 -0500 @@ -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; --- old/makefiles/mapfiles/libjava/mapfile-vers 2013-01-17 16:14:34.145622239 -0500 +++ new/makefiles/mapfiles/libjava/mapfile-vers 2013-01-17 16:14:33.914619843 -0500 @@ -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; --- old/src/share/classes/java/lang/reflect/Constructor.java 2013-01-17 16:14:34.729628297 -0500 +++ new/src/share/classes/java/lang/reflect/Constructor.java 2013-01-17 16:14:34.495625870 -0500 @@ -205,6 +205,11 @@ /** * {@inheritDoc} + */ + public int getParameterCount() { return parameterTypes.length; } + + /** + * {@inheritDoc} * @throws GenericSignatureFormatError {@inheritDoc} * @throws TypeNotPresentException {@inheritDoc} * @throws MalformedParameterizedTypeException {@inheritDoc} --- old/src/share/classes/java/lang/reflect/Executable.java 2013-01-17 16:14:35.348634689 -0500 +++ new/src/share/classes/java/lang/reflect/Executable.java 2013-01-17 16:14:35.116632283 -0500 @@ -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,61 @@ } /** + * 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 +470,5 @@ } return declaredAnnotations; } + } --- old/src/share/classes/java/lang/reflect/Method.java 2013-01-17 16:14:35.933640754 -0500 +++ new/src/share/classes/java/lang/reflect/Method.java 2013-01-17 16:14:35.701638348 -0500 @@ -255,6 +255,12 @@ /** * {@inheritDoc} + */ + public int getParameterCount() { return parameterTypes.length; } + + + /** + * {@inheritDoc} * @throws GenericSignatureFormatError {@inheritDoc} * @throws TypeNotPresentException {@inheritDoc} * @throws MalformedParameterizedTypeException {@inheritDoc} --- old/src/share/classes/java/lang/reflect/Modifier.java 2013-01-17 16:14:36.517646811 -0500 +++ new/src/share/classes/java/lang/reflect/Modifier.java 2013-01-17 16:14:36.284644395 -0500 @@ -337,15 +337,20 @@ // have different meanings for fields and methods and there is no // way to distinguish between the two in this class, or because // they are not Java programming language keywords - static final int BRIDGE = 0x00000040; - static final int VARARGS = 0x00000080; - static final int SYNTHETIC = 0x00001000; - static final int ANNOTATION= 0x00002000; - static final int ENUM = 0x00004000; + static final int BRIDGE = 0x00000040; + static final int VARARGS = 0x00000080; + static final int SYNTHETIC = 0x00001000; + 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. */ --- old/src/share/javavm/export/jvm.h 2013-01-17 16:14:37.105652910 -0500 +++ new/src/share/javavm/export/jvm.h 2013-01-17 16:14:36.865650421 -0500 @@ -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 2013-01-17 05:30:45.060561069 -0500 +++ new/src/share/classes/java/lang/reflect/Parameter.java 2013-01-17 16:14:37.675658652 -0500 @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2012, 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 + * @author Eric McCorkle + */ +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 + * The Java™ Language Specification. + */ + public boolean isSynthesized() { + return Modifier.isSynthesized(getModifiers()); + } + + /** + * Returns {@code true} if this parameter is a synthetic + * construct; returns {@code false} otherwise. + * + * @return true if and only if this parameter is a synthetic + * construct as defined by + * The Java™ Language Specification. + */ + 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} + * @since 1.8 + */ + public T getAnnotation(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + } + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public T[] getAnnotations(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); + } + + /** + * {@inheritDoc} + */ + public Annotation[] getDeclaredAnnotations() { + return executable.getParameterAnnotations()[index]; + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public T getDeclaredAnnotation(Class annotationClass) { + // Only annotations on classes are inherited, for all other + // objects getDeclaredAnnotation is the same as + // getAnnotation. + return getAnnotation(annotationClass); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public T[] getDeclaredAnnotations(Class 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 annotationClass) { + return getAnnotation(annotationClass) != null; + } + + private transient Map, Annotation> declaredAnnotations; + + private synchronized Map, Annotation> declaredAnnotations() { + if(null == declaredAnnotations) { + declaredAnnotations = + new HashMap, Annotation>(); + Annotation[] ann = getDeclaredAnnotations(); + for(int i = 0; i < ann.length; i++) + declaredAnnotations.put(ann[i].annotationType(), ann[i]); + } + return declaredAnnotations; + } + +} --- /dev/null 2013-01-17 05:30:45.060561069 -0500 +++ new/src/share/native/java/lang/reflect/Executable.c 2013-01-17 16:14:38.245664565 -0500 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1994, 2010, 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 +#include + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "java_lang_reflect_Executable.h" + +#define PARAM "L/java/lang/reflect/Parameter;" + +/* +static JNINativeMethod methods[] = { + { "getParameters0", "()[" PARAM, (void*)&JVM_GetParameters } +}; +*/ + +JNIEXPORT jobject JNICALL +Java_java_lang_reflect_Executable_getParameters0(JNIEnv *env, + jobject method) { + return JVM_GetMethodParameters(env, method); +} --- /dev/null 2013-01-17 05:30:45.060561069 -0500 +++ new/test/java/lang/reflect/Parameter/WithParameters.java 2013-01-17 16:14:38.814670465 -0500 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2012, 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 + * @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 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 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 l2, + List l3, + String... rest) {} + } + + @Retention(RetentionPolicy.RUNTIME) + public @interface Thing {} + +} --- /dev/null 2013-01-17 05:30:45.060561069 -0500 +++ new/test/java/lang/reflect/Parameter/WithoutParameters.java 2013-01-17 16:14:39.385676387 -0500 @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2012, 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 l2, + List l3, + String... rest) {} + public class Inner { + int thang; + public Inner(int theng) { + thang = theng + thing; + } + } + } + +}