diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index a09aa2c86a4..6d1aa009755 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -3414,16 +3414,20 @@ public final class Class implements java.io.Serializable, 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 use of type - * Foo to specify the superclass in '... extends Foo' is distinct from the - * declaration 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 use of type Foo to specify the superclass + * in '... extends Foo' is distinct from the declaration of type + * Foo.) * - * If this Class represents a class type whose declaration does not explicitly - * indicate an annotated superclass, the return value is null. + *

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. + *

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 @@ public final class Class implements java.io.Serializable, } /** - * Returns an array of AnnotatedType objects that represent the use of types to - * specify superinterfaces of the entity represented by this Class. (The use - * of type Foo to specify a superinterface in '... implements Foo' is - * distinct from the declaration 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 use of type Foo to specify a + * superinterface in '... implements Foo' is distinct from the + * declaration 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. - * - * 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 + *

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 - * 'extends' clause of the declaration of this Class. + * 'implements' 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 + *

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 {@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. + * + *

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 */ diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java index e84a3360fdd..f92b51d6ff6 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java @@ -27,17 +27,18 @@ package java.lang.reflect; /** - * 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(); } diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java index 4fa089e318c..f1d43c9528e 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java @@ -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(); } diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java index d1ee79f14f4..12d0bfc17bb 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java @@ -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 */ diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java index 3580a14442f..7a39bae492d 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java @@ -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(); } diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java index c357eb9d0bc..2d15f6c9770 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java @@ -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(); } diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index 9d41a0217db..af876c6f4f2 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -514,18 +514,20 @@ public abstract class Executable extends AccessibleObject } /** - * 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 the method + * or constructor represented by this {@code Executable} * - * @return an object representing the return type of this method - * or constructor * @since 1.8 */ public abstract AnnotatedType getAnnotatedReturnType(); @@ -549,24 +551,29 @@ public abstract class Executable extends AccessibleObject } /** - * 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 receiver + * parameter (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 @@ public abstract class Executable extends AccessibleObject } /** - * 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 @@ public abstract class Executable extends AccessibleObject * 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 @@ public abstract class Executable extends AccessibleObject } /** - * 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 @@ public abstract class Executable extends AccessibleObject * 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 */ diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java index e9f3f957c09..9e01fc59ba6 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java @@ -118,6 +118,7 @@ public class AnnotatedTypeFactory { 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; diff --git a/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java index 6b9712a6d4a..12fa1fa687b 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java +++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java @@ -174,6 +174,11 @@ public class TypeAnnotationParser { 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, diff --git a/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedInterfaces.java b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedInterfaces.java new file mode 100644 index 00000000000..6a6d256e551 --- /dev/null +++ b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedInterfaces.java @@ -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 {} +} diff --git a/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedReceiverType.java b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedReceiverType.java new file mode 100644 index 00000000000..e3dd64612c8 --- /dev/null +++ b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedReceiverType.java @@ -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++; + } +} diff --git a/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedSuperclass.java b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedSuperclass.java index d112203a90f..34b95a0a518 100644 --- a/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedSuperclass.java +++ b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedSuperclass.java @@ -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 @@ public class GetAnnotatedSuperclass { 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 @@ public class GetAnnotatedSuperclass { + 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 {} }