8007072: Update Core Reflection for Type Annotations to match latest spec
8022324: j.l.Class.getAnnotatedInterfaces() for array type returns wrong value
8024915: j.l.r.Executable.getAnnotatedReceiverType() should return null for static methods
Summary: Update javadoc and implementation of reflection for type annotations to match latest spec
Reviewed-by: darcy
--- a/jdk/src/share/classes/java/lang/Class.java Fri Sep 27 18:38:00 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Class.java Mon Sep 30 11:18:18 2013 +0200
@@ -3414,16 +3414,20 @@
transient ClassValue.ClassValueMap classValueMap;
/**
- * Returns an AnnotatedType object that represents the use of a type to specify
- * the superclass of the entity represented by this Class. (The <em>use</em> of type
- * Foo to specify the superclass in '... extends Foo' is distinct from the
- * <em>declaration</em> of type Foo.)
+ * Returns an {@code AnnotatedType} object that represents the use of a
+ * type to specify the superclass of the entity represented by this {@code
+ * Class} object. (The <em>use</em> of type Foo to specify the superclass
+ * in '... extends Foo' is distinct from the <em>declaration</em> of type
+ * Foo.)
*
- * If this Class represents a class type whose declaration does not explicitly
- * indicate an annotated superclass, the return value is null.
+ * <p> If this {@code Class} object represents a type whose declaration
+ * does not explicitly indicate an annotated superclass, then the return
+ * value is an {@code AnnotatedType} object representing an element with no
+ * annotations.
*
- * If this Class represents either the Object class, an interface type, an
- * array type, a primitive type, or void, the return value is null.
+ * <p> If this {@code Class} represents either the {@code Object} class, an
+ * interface type, an array type, a primitive type, or void, the return
+ * value is {@code null}.
*
* @return an object representing the superclass
* @since 1.8
@@ -3441,30 +3445,33 @@
}
/**
- * Returns an array of AnnotatedType objects that represent the use of types to
- * specify superinterfaces of the entity represented by this Class. (The <em>use</em>
- * of type Foo to specify a superinterface in '... implements Foo' is
- * distinct from the <em>declaration</em> of type Foo.)
+ * Returns an array of {@code AnnotatedType} objects that represent the use
+ * of types to specify superinterfaces of the entity represented by this
+ * {@code Class} object. (The <em>use</em> of type Foo to specify a
+ * superinterface in '... implements Foo' is distinct from the
+ * <em>declaration</em> of type Foo.)
*
- * If this Class represents a class, the return value is an array
- * containing objects representing the uses of interface types to specify
- * interfaces implemented by the class. The order of the objects in the
- * array corresponds to the order of the interface types used in the
- * 'implements' clause of the declaration of this Class.
+ * <p> If this {@code Class} object represents a class, the return value is
+ * an array containing objects representing the uses of interface types to
+ * specify interfaces implemented by the class. The order of the objects in
+ * the array corresponds to the order of the interface types used in the
+ * 'implements' clause of the declaration of this {@code Class} object.
*
- * If this Class represents an interface, the return value is an array
- * containing objects representing the uses of interface types to specify
- * interfaces directly extended by the interface. The order of the objects in
- * the array corresponds to the order of the interface types used in the
- * 'extends' clause of the declaration of this Class.
+ * <p> If this {@code Class} object represents an interface, the return
+ * value is an array containing objects representing the uses of interface
+ * types to specify interfaces directly extended by the interface. The
+ * order of the objects in the array corresponds to the order of the
+ * interface types used in the 'extends' clause of the declaration of this
+ * {@code Class} object.
*
- * If this Class represents a class or interface whose declaration does not
- * explicitly indicate any annotated superinterfaces, the return value is an
+ * <p> If this {@code Class} object represents a class or interface whose
+ * declaration does not explicitly indicate any annotated superinterfaces,
+ * the return value is an array of length 0.
+ *
+ * <p> If this {@code Class} object represents either the {@code Object}
+ * class, an array type, a primitive type, or void, the return value is an
* array of length 0.
*
- * If this Class represents either the Object class, an array type, a
- * primitive type, or void, the return value is an array of length 0.
- *
* @return an array representing the superinterfaces
* @since 1.8
*/
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java Fri Sep 27 18:38:00 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java Mon Sep 30 11:18:18 2013 +0200
@@ -27,17 +27,18 @@
/**
- * AnnotatedArrayType represents the use of an array type, whose component
- * type may itself represent the annotated use of a type.
+ * {@code AnnotatedArrayType} represents the potentially annotated use of an
+ * array type, whose component type may itself represent the annotated use of a
+ * type.
*
* @since 1.8
*/
public interface AnnotatedArrayType extends AnnotatedType {
/**
- * Returns the annotated generic component type of this array type.
+ * Returns the potentially annotated generic component type of this array type.
*
- * @return the annotated generic component type of this array type
+ * @return the potentially annotated generic component type of this array type
*/
AnnotatedType getAnnotatedGenericComponentType();
}
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java Fri Sep 27 18:38:00 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java Mon Sep 30 11:18:18 2013 +0200
@@ -26,17 +26,18 @@
package java.lang.reflect;
/**
- * AnnotatedParameterizedType represents the use of a parameterized type,
- * whose type arguments may themselves represent annotated uses of types.
+ * {@code AnnotatedParameterizedType} represents the potentially annotated use
+ * of a parameterized type, whose type arguments may themselves represent
+ * annotated uses of types.
*
* @since 1.8
*/
public interface AnnotatedParameterizedType extends AnnotatedType {
/**
- * Returns the annotated actual type arguments of this parameterized type.
+ * Returns the potentially annotated actual type arguments of this parameterized type.
*
- * @return the annotated actual type arguments of this parameterized type
+ * @return the potentially annotated actual type arguments of this parameterized type
*/
AnnotatedType[] getAnnotatedActualTypeArguments();
}
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java Fri Sep 27 18:38:00 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java Mon Sep 30 11:18:18 2013 +0200
@@ -26,10 +26,10 @@
package java.lang.reflect;
/**
- * AnnotatedType represents the annotated use of a type in the program
- * currently running in this VM. The use may be of any type in the Java
- * programming language, including an array type, a parameterized type, a type
- * variable, or a wildcard type.
+ * {@code AnnotatedType} represents the potentially annotated use of a type in
+ * the program currently running in this VM. The use may be of any type in the
+ * Java programming language, including an array type, a parameterized type, a
+ * type variable, or a wildcard type.
*
* @since 1.8
*/
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java Fri Sep 27 18:38:00 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java Mon Sep 30 11:18:18 2013 +0200
@@ -26,18 +26,18 @@
package java.lang.reflect;
/**
- * AnnotatedTypeVariable represents the use of a type variable, whose
- * declaration may have bounds which themselves represent annotated uses of
- * types.
+ * {@code AnnotatedTypeVariable} represents the potentially annotated use of a
+ * type variable, whose declaration may have bounds which themselves represent
+ * annotated uses of types.
*
* @since 1.8
*/
public interface AnnotatedTypeVariable extends AnnotatedType {
/**
- * Returns the annotated bounds of this type variable.
+ * Returns the potentially annotated bounds of this type variable.
*
- * @return the annotated bounds of this type variable
+ * @return the potentially annotated bounds of this type variable
*/
AnnotatedType[] getAnnotatedBounds();
}
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java Fri Sep 27 18:38:00 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java Mon Sep 30 11:18:18 2013 +0200
@@ -26,24 +26,25 @@
package java.lang.reflect;
/**
- * AnnotatedWildcardType represents the use of a wildcard type argument, whose
- * upper or lower bounds may themselves represent annotated uses of types.
+ * {@code AnnotatedWildcardType} represents the potentially annotated use of a
+ * wildcard type argument, whose upper or lower bounds may themselves represent
+ * annotated uses of types.
*
* @since 1.8
*/
public interface AnnotatedWildcardType extends AnnotatedType {
/**
- * Returns the annotated lower bounds of this wildcard type.
+ * Returns the potentially annotated lower bounds of this wildcard type.
*
- * @return the annotated lower bounds of this wildcard type
+ * @return the potentially annotated lower bounds of this wildcard type
*/
AnnotatedType[] getAnnotatedLowerBounds();
/**
- * Returns the annotated upper bounds of this wildcard type.
+ * Returns the potentially annotated upper bounds of this wildcard type.
*
- * @return the annotated upper bounds of this wildcard type
+ * @return the potentially annotated upper bounds of this wildcard type
*/
AnnotatedType[] getAnnotatedUpperBounds();
}
--- a/jdk/src/share/classes/java/lang/reflect/Executable.java Fri Sep 27 18:38:00 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/Executable.java Mon Sep 30 11:18:18 2013 +0200
@@ -514,18 +514,20 @@
}
/**
- * Returns an AnnotatedType object that represents the use of a type to
+ * Returns an {@code AnnotatedType} object that represents the use of a type to
* specify the return type of the method/constructor represented by this
* Executable.
*
- * If this Executable represents a constructor, the AnnotatedType object
- * represents the type of the constructed object.
+ * If this {@code Executable} object represents a constructor, the {@code
+ * AnnotatedType} object represents the type of the constructed object.
*
- * If this Executable represents a method, the AnnotatedType object
- * represents the use of a type to specify the return type of the method.
+ * If this {@code Executable} object represents a method, the {@code
+ * AnnotatedType} object represents the use of a type to specify the return
+ * type of the method.
*
- * @return an object representing the return type of this method
- * or constructor
+ * @return an object representing the return type of the method
+ * or constructor represented by this {@code Executable}
+ *
* @since 1.8
*/
public abstract AnnotatedType getAnnotatedReturnType();
@@ -549,24 +551,29 @@
}
/**
- * Returns an AnnotatedType object that represents the use of a type to
- * specify the receiver type of the method/constructor represented by this
- * Executable. The receiver type of a method/constructor is available only
- * if the method/constructor declares a formal parameter called 'this'.
+ * Returns an {@code AnnotatedType} object that represents the use of a
+ * type to specify the receiver type of the method/constructor represented
+ * by this Executable object. The receiver type of a method/constructor is
+ * available only if the method/constructor has a <em>receiver
+ * parameter</em> (JLS 8.4.1).
*
- * Returns null if this Executable represents a constructor or instance
- * method that either declares no formal parameter called 'this', or
- * declares a formal parameter called 'this' with no annotations on its
- * type.
+ * If this {@code Executable} object represents a constructor or instance
+ * method that does not have a receiver parameter, or has a receiver
+ * parameter with no annotations on its type, then the return value is an
+ * {@code AnnotatedType} object representing an element with no
+ * annotations.
*
- * Returns null if this Executable represents a static method.
+ * If this {@code Executable} object represents a static method, then the
+ * return value is null.
*
- * @return an object representing the receiver type of the
- * method or constructor represented by this Executable
+ * @return an object representing the receiver type of the method or
+ * constructor represented by this {@code Executable}
*
* @since 1.8
*/
public AnnotatedType getAnnotatedReceiverType() {
+ if (Modifier.isStatic(this.getModifiers()))
+ return null;
return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(),
sun.misc.SharedSecrets.getJavaLangAccess().
getConstantPool(getDeclaringClass()),
@@ -577,8 +584,8 @@
}
/**
- * Returns an array of AnnotatedType objects that represent the use of
- * types to specify formal parameter types of the method/constructor
+ * Returns an array of {@code AnnotatedType} objects that represent the use
+ * of types to specify formal parameter types of the method/constructor
* represented by this Executable. The order of the objects in the array
* corresponds to the order of the formal parameter types in the
* declaration of the method/constructor.
@@ -587,7 +594,8 @@
* parameters.
*
* @return an array of objects representing the types of the
- * formal parameters of this method or constructor
+ * formal parameters of the method or constructor represented by this
+ * {@code Executable}
*
* @since 1.8
*/
@@ -602,8 +610,8 @@
}
/**
- * Returns an array of AnnotatedType objects that represent the use of
- * types to specify the declared exceptions of the method/constructor
+ * Returns an array of {@code AnnotatedType} objects that represent the use
+ * of types to specify the declared exceptions of the method/constructor
* represented by this Executable. The order of the objects in the array
* corresponds to the order of the exception types in the declaration of
* the method/constructor.
@@ -612,7 +620,8 @@
* exceptions.
*
* @return an array of objects representing the declared
- * exceptions of this method or constructor
+ * exceptions of the method or constructor represented by this {@code
+ * Executable}
*
* @since 1.8
*/
--- a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Fri Sep 27 18:38:00 2013 -0700
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Mon Sep 30 11:18:18 2013 +0200
@@ -118,6 +118,7 @@
static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION,
new TypeAnnotation[0], new TypeAnnotation[0], null);
+ static final AnnotatedType[] EMPTY_ANNOTATED_TYPE_ARRAY = new AnnotatedType[0];
private static class AnnotatedTypeBaseImpl implements AnnotatedType {
private final Type type;
--- a/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java Fri Sep 27 18:38:00 2013 -0700
+++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java Mon Sep 30 11:18:18 2013 +0200
@@ -174,6 +174,11 @@
public static AnnotatedType[] buildAnnotatedInterfaces(byte[] rawAnnotations,
ConstantPool cp,
Class<?> decl) {
+ if (decl == Object.class ||
+ decl.isArray() ||
+ decl.isPrimitive() ||
+ decl == Void.TYPE)
+ return AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE_ARRAY;
return buildAnnotatedTypes(rawAnnotations,
cp,
decl,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedInterfaces.java Mon Sep 30 11:18:18 2013 +0200
@@ -0,0 +1,80 @@
+/*
+ * 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
+ * @bug 8022324
+ * @summary Test Class.getAnnotatedInterfaces() returns 0-length array as
+ * specified.
+ */
+
+import java.lang.reflect.AnnotatedType;
+import java.util.Arrays;
+
+public class GetAnnotatedInterfaces {
+ private static final Class<?>[] testData = {
+ GetAnnotatedInterfaces.class,
+ (new Clz() {}).getClass(),
+ (new Object() {}).getClass(),
+ Object[].class,
+ Object[][].class,
+ Object[][][].class,
+ Object.class,
+ void.class,
+ int.class,
+ };
+
+ private static int failed = 0;
+ private static int tests = 0;
+
+ public static void main(String[] args) throws Exception {
+ testReturnsZeroLengthArray();
+
+ if (failed != 0)
+ throw new RuntimeException("Test failed, check log for details");
+ if (tests != 9)
+ throw new RuntimeException("Not all cases ran, failing");
+ }
+
+ private static void testReturnsZeroLengthArray() {
+ for (Class<?> toTest : testData) {
+ tests++;
+
+ AnnotatedType[] res = toTest.getAnnotatedInterfaces();
+
+ if (res == null) {
+ failed++;
+ System.out.println(toTest + ".class.getAnnotatedInterface() returns" +
+ "'null' should zero length array");
+ } else if (res.length != 0) {
+ failed++;
+ System.out.println(toTest + ".class.getAnnotatedInterfaces() returns: "
+ + Arrays.asList(res) + ", should be a zero length array of AnnotatedType");
+ }
+ }
+ }
+
+ interface If {}
+
+ static abstract class Clz {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedReceiverType.java Mon Sep 30 11:18:18 2013 +0200
@@ -0,0 +1,83 @@
+/*
+ * 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
+ * @bug 8024915
+ */
+
+import java.lang.reflect.AnnotatedType;
+import java.util.Arrays;
+
+public class GetAnnotatedReceiverType {
+ public void method() {}
+ public void method0(GetAnnotatedReceiverType this) {}
+ public static void method4() {}
+
+ class Inner0 {
+ public Inner0() {}
+ }
+
+ class Inner1 {
+ public Inner1(GetAnnotatedReceiverType GetAnnotatedReceiverType.this) {}
+ }
+
+ private static int failures = 0;
+ private static int tests = 0;
+
+ public static void main(String[] args) throws NoSuchMethodException {
+ checkEmptyAT(GetAnnotatedReceiverType.class.getMethod("method").getAnnotatedReceiverType(),
+ "getAnnotatedReceiverType for \"method\" should return an empty AnnotatedType");
+ checkEmptyAT(Inner0.class.getConstructor(GetAnnotatedReceiverType.class).getAnnotatedReceiverType(),
+ "getAnnotatedReceiverType for a ctor without a \"this\" should return an empty AnnotatedType");
+
+ checkEmptyAT(GetAnnotatedReceiverType.class.getMethod("method0").getAnnotatedReceiverType(),
+ "getAnnotatedReceiverType for \"method0\" should return an empty AnnotatedType");
+ checkEmptyAT(Inner1.class.getConstructor(GetAnnotatedReceiverType.class).getAnnotatedReceiverType(),
+ "getAnnotatedReceiverType for a ctor with a \"this\" should return an empty AnnotatedType");
+
+ checkNull(GetAnnotatedReceiverType.class.getMethod("method4").getAnnotatedReceiverType(),
+ "getAnnotatedReceiverType() on a static method should return null");
+
+ if (failures != 0)
+ throw new RuntimeException("Test failed, see log for details");
+ else if (tests != 5)
+ throw new RuntimeException("Not all cases ran, failing");
+ }
+
+ private static void checkNull(Object o, String msg) {
+ if (o != null) {
+ failures++;
+ System.err.println(msg);
+ }
+ tests++;
+ }
+
+ private static void checkEmptyAT(AnnotatedType a, String msg) {
+ if (a.getAnnotations().length != 0) {
+ failures++;
+ System.err.print(msg);
+ }
+ tests++;
+ }
+}
--- a/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedSuperclass.java Fri Sep 27 18:38:00 2013 -0700
+++ b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedSuperclass.java Mon Sep 30 11:18:18 2013 +0200
@@ -23,12 +23,16 @@
/*
* @test
- * @bug 8022343
- * @summary make sure Class.getAnnotatedSuperclass() returns null when specified to do so
+ * @bug 8022343 8007072
+ * @summary Test Class.getAnnotatedSuperclass() returns null/non-null
+ * AnnotatedType as specified
*/
+import java.lang.reflect.AnnotatedType;
+import java.util.Arrays;
+
public class GetAnnotatedSuperclass {
- private static final Class<?>[] testData = {
+ private static final Class<?>[] nullTestData = {
Object.class,
If.class,
Object[].class,
@@ -36,9 +40,31 @@
int.class,
};
+ private static final Class<?>[] nonNullTestData = {
+ Class.class,
+ GetAnnotatedSuperclass.class,
+ (new If() {}).getClass(),
+ (new Clz() {}).getClass(),
+ (new Object() {}).getClass(),
+ };
+
+ private static int failed = 0;
+ private static int tests = 0;
+
public static void main(String[] args) throws Exception {
- int failed = 0;
- for (Class<?> toTest : testData) {
+ testReturnsNull();
+ testReturnsEmptyAT();
+
+ if (failed != 0)
+ throw new RuntimeException("Test failed, check log for details");
+ if (tests != 10)
+ throw new RuntimeException("Not all cases ran, failing");
+ }
+
+ private static void testReturnsNull() {
+ for (Class<?> toTest : nullTestData) {
+ tests++;
+
Object res = toTest.getAnnotatedSuperclass();
if (res != null) {
@@ -47,10 +73,26 @@
+ res + ", should be null");
}
}
+ }
- if (failed != 0)
- throw new RuntimeException("Test failed, check log for details");
+ private static void testReturnsEmptyAT() {
+ for (Class<?> toTest : nonNullTestData) {
+ tests++;
+
+ AnnotatedType res = toTest.getAnnotatedSuperclass();
+
+ if (res == null) {
+ failed++;
+ System.out.println(toTest + ".getAnnotatedSuperclass() returns 'null' should be non-null");
+ } else if (res.getAnnotations().length != 0) {
+ failed++;
+ System.out.println(toTest + ".getAnnotatedSuperclass() returns: "
+ + Arrays.asList(res.getAnnotations()) + ", should be an empty AnnotatedType");
+ }
+ }
}
interface If {}
+
+ static abstract class Clz {}
}