undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,321 @@
/*
* Copyright (c) 2016, 2024, 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 8162817 8168921 8322218
* @summary Test of toString on normal annotations
*/
// See also the sibling compile-time test
// test/langtools/tools/javac/processing/model/element/AnnotationToStringTest.java
import java.lang.annotation.*;
import java.lang.reflect.Field;
import javax.lang.model.element.Modifier;
import java.util.*;
/**
* The expected string values are stored in @ExpectedString
* annotations. The essence of the test is comparing the toString()
* result of annotations to the corresponding ExpectedString.value().
*/
public class AnnotationToStringTest {
public static void main(String... args) throws Exception {
int failures = 0;
failures += check(PrimHost.class.getAnnotation(ExpectedString.class).value(),
PrimHost.class.getAnnotation(MostlyPrimitive.class).toString());
failures += classyTest();
failures += arrayAnnotationTest();
if (failures > 0)
throw new RuntimeException(failures + " failures");
}
private static int check(String expected, String actual) {
if (!expected.equals(actual)) {
System.err.printf("ERROR: Expected ''%s'';%ngot ''%s''.\n",
expected, actual);
return 1;
} else
return 0;
}
@ExpectedString(
"@MostlyPrimitive(c0='a', "+
"c1='\\'', " +
"b0=(byte)0x01, " +
"i0=1, " +
"i1=2, " +
"f0=1.0f, " +
"f1=0.0f/0.0f, " +
"d0=0.0, " +
"d1=1.0/0.0, " +
"l0=5L, " +
"l1=9223372036854775807L, " +
"l2=-9223372036854775808L, " +
"l3=-2147483648L, " +
"s0=\"Hello world.\", " +
"s1=\"a\\\"b\", " +
"class0=Obj[].class, " +
"classArray={Obj[].class})")
@MostlyPrimitive(
c0='a',
c1='\'',
b0=1,
i0=1,
i1=2,
f0=1.0f,
f1=Float.NaN,
d0=0.0,
d1=2.0/0.0,
l0=5,
l1=Long.MAX_VALUE,
l2=Long.MIN_VALUE,
l3=Integer.MIN_VALUE,
s0="Hello world.",
s1="a\"b",
class0=Obj[].class,
classArray={Obj[].class}
)
static class PrimHost{}
private static int classyTest() {
int failures = 0;
for (Field f : AnnotationHost.class.getFields()) {
Annotation a = f.getAnnotation(Classy.class);
System.out.println(a);
failures += check(f.getAnnotation(ExpectedString.class).value(),
a.toString());
}
return failures;
}
static class AnnotationHost {
@ExpectedString(
"@Classy(Obj.class)")
@Classy(Obj.class)
public int f0;
@ExpectedString(
"@Classy(Obj[].class)")
@Classy(Obj[].class)
public int f1;
@ExpectedString(
"@Classy(Obj[][].class)")
@Classy(Obj[][].class)
public int f2;
@ExpectedString(
"@Classy(Obj[][][].class)")
@Classy(Obj[][][].class)
public int f3;
@ExpectedString(
"@Classy(int.class)")
@Classy(int.class)
public int f4;
@ExpectedString(
"@Classy(int[][][].class)")
@Classy(int[][][].class)
public int f5;
}
/**
* Each field should have two annotations, the first being
* @ExpectedString and the second the annotation under test.
*/
private static int arrayAnnotationTest() {
int failures = 0;
for (Field f : ArrayAnnotationHost.class.getFields()) {
Annotation[] annotations = f.getAnnotations();
System.out.println(annotations[1]);
failures += check(((ExpectedString)annotations[0]).value(),
annotations[1].toString());
}
return failures;
}
static class ArrayAnnotationHost {
@ExpectedString(
"@EnumValue(NON_SEALED)") // toString and name differ
@EnumValue(Modifier.NON_SEALED)
public int f00;
@ExpectedString(
"@BooleanArray({true, false, true})")
@BooleanArray({true, false, true})
public boolean[] f0;
@ExpectedString(
"@FloatArray({3.0f, 4.0f, 0.0f/0.0f, -1.0f/0.0f, 1.0f/0.0f})")
@FloatArray({3.0f, 4.0f, Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY})
public float[] f1;
@ExpectedString(
"@DoubleArray({1.0, 2.0, 0.0/0.0, 1.0/0.0, -1.0/0.0})")
@DoubleArray({1.0, 2.0, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY,})
public double[] f2;
@ExpectedString(
"@ByteArray({(byte)0x0a, (byte)0x0b, (byte)0x0c})")
@ByteArray({10, 11, 12})
public byte[] f3;
@ExpectedString(
"@ShortArray({0, 4, 5})")
@ShortArray({0, 4, 5})
public short[] f4;
@ExpectedString(
"@CharArray({'a', 'b', 'c', '\\'', '\"'})")
@CharArray({'a', 'b', 'c', '\'', '"'})
public char[] f5;
@ExpectedString(
"@IntArray({1})")
@IntArray({1})
public int[] f6;
@ExpectedString(
"@LongArray({-9223372036854775808L, -2147483649L, -2147483648L," +
" -2147483647L, 2147483648L, 9223372036854775807L})")
@LongArray({Long.MIN_VALUE, Integer.MIN_VALUE-1L, Integer.MIN_VALUE,
-Integer.MAX_VALUE, Integer.MAX_VALUE+1L, Long.MAX_VALUE})
public long[] f7;
@ExpectedString(
"@StringArray({\"A\", \"B\", \"C\", \"\\\"Quote\\\"\", \"'\", \"\\\"\"})")
@StringArray({"A", "B", "C", "\"Quote\"", "'", "\""})
public String[] f8;
@ExpectedString(
"@ClassArray({int.class, Obj[].class})")
@ClassArray({int.class, Obj[].class})
public Class<?>[] f9;
@ExpectedString(
"@EnumArray({SEALED, NON_SEALED, PUBLIC})")
@EnumArray({Modifier.SEALED, Modifier.NON_SEALED, Modifier.PUBLIC})
public RetentionPolicy[] f10;
}
}
// ------------ Supporting types ------------
class Obj {}
@Retention(RetentionPolicy.RUNTIME)
@interface EnumValue {
Modifier value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface ExpectedString {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface Classy {
Class<?> value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface BooleanArray {
boolean[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface FloatArray {
float[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface DoubleArray {
double[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface ByteArray {
byte[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface ShortArray {
short[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface CharArray {
char[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface IntArray {
int[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface LongArray {
long[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface ClassArray {
Class<?>[] value() default {int.class, Obj[].class};
}
@Retention(RetentionPolicy.RUNTIME)
@interface StringArray {
String[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface EnumArray {
Modifier[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface MostlyPrimitive {
char c0();
char c1();
byte b0();
int i0();
int i1();
float f0();
float f1();
double d0();
double d1();
long l0();
long l1();
long l2();
long l3();
String s0();
String s1();
Class<?> class0();
Class<?>[] classArray();
}

View file

@ -0,0 +1,102 @@
/*
* Copyright (c) 2013, 2015, 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 7122142
* @summary Test deadlock situation when recursive annotations are parsed
* @modules java.management
*/
import java.lang.annotation.Retention;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
public class AnnotationTypeDeadlockTest {
@Retention(RUNTIME)
@AnnB
public @interface AnnA {
}
@Retention(RUNTIME)
@AnnA
public @interface AnnB {
}
static class Task extends Thread {
final CountDownLatch prepareLatch;
final AtomicInteger goLatch;
final Class<?> clazz;
Task(CountDownLatch prepareLatch, AtomicInteger goLatch, Class<?> clazz) {
super(clazz.getSimpleName());
setDaemon(true); // in case it deadlocks
this.prepareLatch = prepareLatch;
this.goLatch = goLatch;
this.clazz = clazz;
}
@Override
public void run() {
prepareLatch.countDown(); // notify we are prepared
while (goLatch.get() > 0); // spin-wait before go
clazz.getDeclaredAnnotations();
}
}
public static void main(String[] args) throws Exception {
CountDownLatch prepareLatch = new CountDownLatch(2);
AtomicInteger goLatch = new AtomicInteger(1);
Task taskA = new Task(prepareLatch, goLatch, AnnA.class);
Task taskB = new Task(prepareLatch, goLatch, AnnB.class);
taskA.start();
taskB.start();
// wait until both threads start-up
prepareLatch.await();
// let them go
goLatch.set(0);
// obtain ThreadMXBean
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
// wait for threads to finish or dead-lock
while (taskA.isAlive() || taskB.isAlive()) {
// attempt to join threads
taskA.join(500L);
taskB.join(500L);
// detect dead-lock
long[] deadlockedIds = threadBean.findMonitorDeadlockedThreads();
if (deadlockedIds != null && deadlockedIds.length > 0) {
StringBuilder sb = new StringBuilder("deadlock detected:\n\n");
for (ThreadInfo ti : threadBean.getThreadInfo(deadlockedIds, Integer.MAX_VALUE)) {
sb.append(ti);
}
throw new IllegalStateException(sb.toString());
}
}
}
}

View file

@ -0,0 +1,175 @@
/*
* Copyright (c) 2013, 2017, 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 Test consistent parsing of ex-RUNTIME annotations that
* were changed and separately compiled to have CLASS retention
* @run main AnnotationTypeRuntimeAssumptionTest
*/
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import static java.lang.annotation.RetentionPolicy.CLASS;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* This test simulates a situation where there are two mutually recursive
* {@link RetentionPolicy#RUNTIME RUNTIME} annotations {@link AnnA_v1 AnnA_v1}
* and {@link AnnB AnnB} and then the first is changed to have
* {@link RetentionPolicy#CLASS CLASS} retention and separately compiled.
* When {@link AnnA_v1 AnnA_v1} annotation is looked-up on {@link AnnB AnnB}
* it still appears to have {@link RetentionPolicy#RUNTIME RUNTIME} retention.
*/
public class AnnotationTypeRuntimeAssumptionTest {
@Retention(RUNTIME)
@AnnB
public @interface AnnA_v1 {
}
// An alternative version of AnnA_v1 with CLASS retention instead.
// Used to simulate separate compilation (see AltClassLoader below).
@Retention(CLASS)
@AnnB
public @interface AnnA_v2 {
}
@Retention(RUNTIME)
@AnnA_v1
public @interface AnnB {
}
@AnnA_v1
public static class TestTask implements Runnable {
@Override
public void run() {
AnnA_v1 ann1 = TestTask.class.getDeclaredAnnotation(AnnA_v1.class);
if (ann1 != null) {
throw new IllegalStateException(
"@" + ann1.annotationType().getSimpleName() +
" found on: " + TestTask.class.getName() +
" should not be visible at runtime");
}
AnnA_v1 ann2 = AnnB.class.getDeclaredAnnotation(AnnA_v1.class);
if (ann2 != null) {
throw new IllegalStateException(
"@" + ann2.annotationType().getSimpleName() +
" found on: " + AnnB.class.getName() +
" should not be visible at runtime");
}
}
}
public static void main(String[] args) throws Exception {
ClassLoader altLoader = new AltClassLoader(
AnnotationTypeRuntimeAssumptionTest.class.getClassLoader());
Runnable altTask = (Runnable) Class.forName(
TestTask.class.getName(),
true,
altLoader).newInstance();
altTask.run();
}
/**
* A ClassLoader implementation that loads alternative implementations of
* classes. If class name ends with "_v1" it locates instead a class with
* name ending with "_v2" and loads that class instead.
*/
static class AltClassLoader extends ClassLoader {
AltClassLoader(ClassLoader parent) {
super(parent);
}
@Override
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
if (name.indexOf('.') < 0) { // root package is our class
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
c = findClass(name);
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
else { // not our class
return super.loadClass(name, resolve);
}
}
@Override
protected Class<?> findClass(String name)
throws ClassNotFoundException {
// special class name -> replace it with alternative name
if (name.endsWith("_v1")) {
String altName = name.substring(0, name.length() - 3) + "_v2";
String altPath = altName.replace('.', '/').concat(".class");
try (InputStream is = getResourceAsStream(altPath)) {
if (is != null) {
byte[] bytes = is.readAllBytes();
// patch class bytes to contain original name
for (int i = 0; i < bytes.length - 2; i++) {
if (bytes[i] == '_' &&
bytes[i + 1] == 'v' &&
bytes[i + 2] == '2') {
bytes[i + 2] = '1';
}
}
return defineClass(name, bytes, 0, bytes.length);
}
else {
throw new ClassNotFoundException(name);
}
}
catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
}
else { // not special class name -> just load the class
String path = name.replace('.', '/').concat(".class");
try (InputStream is = getResourceAsStream(path)) {
if (is != null) {
byte[] bytes = is.readAllBytes();
return defineClass(name, bytes, 0, bytes.length);
}
else {
throw new ClassNotFoundException(name);
}
}
catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
}
}
}
}

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2020, 2024, 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 8228988 8266598
* @summary An annotation-typed property of an annotation that is represented as an
* incompatible property of another type should yield an AnnotationTypeMismatchException.
* @run main AnnotationTypeMismatchTest
*/
import java.lang.annotation.AnnotationTypeMismatchException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.classfile.Annotation;
import java.lang.classfile.AnnotationElement;
import java.lang.classfile.AnnotationValue;
import java.lang.classfile.ClassFile;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.lang.constant.ClassDesc;
import static java.lang.constant.ConstantDescs.CD_Object;
public class AnnotationTypeMismatchTest {
public static void main(String[] args) throws Exception {
/*
* @AnAnnotation(value = AnEnum.VALUE) // would now be: value = @Value
* class Carrier { }
*/
byte[] b = ClassFile.of().build(ClassDesc.of("sample", "Carrier"), clb -> {
clb.withSuperclass(CD_Object);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(
AnAnnotation.class.describeConstable().orElseThrow(),
AnnotationElement.of("value", AnnotationValue.of(AnEnum.VALUE))
)
));
});
ByteArrayClassLoader cl = new ByteArrayClassLoader(AnnotationTypeMismatchTest.class.getClassLoader());
cl.init(b);
AnAnnotation sample = cl.loadClass("sample.Carrier").getAnnotation(AnAnnotation.class);
try {
Value value = sample.value();
throw new IllegalStateException("Found value: " + value);
} catch (AnnotationTypeMismatchException e) {
if (!e.element().getName().equals("value")) {
throw new IllegalStateException("Unexpected element: " + e.element());
} else if (!e.foundType().equals(AnEnum.class.getName() + "." + AnEnum.VALUE.name())) {
throw new IllegalStateException("Unexpected type: " + e.foundType());
}
}
}
public enum AnEnum {
VALUE
}
@Retention(RetentionPolicy.RUNTIME)
public @interface AnAnnotation {
Value value() default @Value;
}
public @interface Value { }
public static class ByteArrayClassLoader extends ClassLoader {
public ByteArrayClassLoader(ClassLoader parent) {
super(parent);
}
public void init(byte[] b) {
defineClass("sample.Carrier", b, 0, b.length);
}
}
}

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2021, 2024, 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 8266791
* @summary Annotation property which is compiled as an array property but
* changed observed as a singular element should throw an
* AnnotationTypeMismatchException
* @run main ArityTypeMismatchTest
*/
import java.lang.annotation.AnnotationTypeMismatchException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.classfile.Annotation;
import java.lang.classfile.AnnotationElement;
import java.lang.classfile.AnnotationValue;
import java.lang.classfile.ClassFile;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.lang.constant.ClassDesc;
import static java.lang.constant.ConstantDescs.CD_Object;
public class ArityTypeMismatchTest {
public static void main(String[] args) throws Exception {
/*
* This test creates an annotation with a member with a non-array type where the annotation
* defines an array property of this type. This can happen if the annotation class is recompiled
* without recompiling the code that declares an annotation of this type. In the example, a
* class is defined to be annotated as
*
* @AnAnnotation(value = {"v"}) // should no longer be an array
* class Carrier { }
*
* where @AnAnnotation expects a singular value.
*/
byte[] b = ClassFile.of().build(ClassDesc.of("sample", "Carrier"), clb -> {
clb.withSuperclass(CD_Object);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(
AnAnnotation.class.describeConstable().orElseThrow(),
AnnotationElement.of("value", AnnotationValue.of(new String[] {"v"}))
)
));
});
ByteArrayClassLoader cl = new ByteArrayClassLoader(ArityTypeMismatchTest.class.getClassLoader());
cl.init(b);
AnAnnotation sample = cl.loadClass("sample.Carrier").getAnnotation(AnAnnotation.class);
try {
String value = sample.value();
throw new IllegalStateException("Found value: " + value);
} catch (AnnotationTypeMismatchException e) {
if (!e.element().getName().equals("value")) {
throw new IllegalStateException("Unexpected element: " + e.element());
} else if (!e.foundType().equals("Array with component tag: s")) {
throw new IllegalStateException("Unexpected type: " + e.foundType());
}
}
}
@Retention(RetentionPolicy.RUNTIME)
public @interface AnAnnotation {
String value();
}
public static class ByteArrayClassLoader extends ClassLoader {
public ByteArrayClassLoader(ClassLoader parent) {
super(parent);
}
public void init(byte[] b) {
defineClass("sample.Carrier", b, 0, b.length);
}
}
}

View file

@ -0,0 +1,132 @@
/*
* Copyright (c) 2021, 2024, 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 8266766
* @summary An array property of a type that is no longer of a type that is a legal member of an
* annotation should throw an AnnotationTypeMismatchException.
* @run main ArrayTypeMismatchTest
*/
import java.lang.annotation.Annotation;
import java.lang.annotation.AnnotationTypeMismatchException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.classfile.AnnotationElement;
import java.lang.classfile.AnnotationValue;
import java.lang.classfile.ClassFile;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.lang.reflect.AccessFlag;
import java.lang.reflect.InvocationTargetException;
import static java.lang.classfile.ClassFile.ACC_ABSTRACT;
import static java.lang.classfile.ClassFile.ACC_PUBLIC;
import static java.lang.constant.ConstantDescs.CD_Object;
public class ArrayTypeMismatchTest {
public static void main(String[] args) throws Exception {
/*
* This test creates an annotation where the annotation member's type is an array with
* a component type that cannot be legally used for an annotation member. This can happen
* if a class is recompiled independencly of the annotation type and linked at runtime
* in this new version. For a test, a class is created as:
*
* package sample;
* @Carrier(value = { @NoAnnotation })
* class Host { }
*
* where NoAnnotation is defined as a regular interface and not as an annotation type.
* The classes are created by using ASM to emulate this state.
*/
ByteArrayClassLoader cl = new ByteArrayClassLoader(NoAnnotation.class.getClassLoader());
cl.init(annotationType(), carrierType());
@SuppressWarnings("unchecked")
Class<? extends Annotation> host = (Class<? extends Annotation>) cl.loadClass("sample.Host");
Annotation sample = cl.loadClass("sample.Carrier").getAnnotation(host);
try {
Object value = host.getMethod("value").invoke(sample);
throw new IllegalStateException("Found value: " + value);
} catch (InvocationTargetException ite) {
Throwable cause = ite.getCause();
if (cause instanceof AnnotationTypeMismatchException e) {
if (!e.element().getName().equals("value")) {
throw new IllegalStateException("Unexpected element: " + e.element());
} else if (!e.foundType().equals("Array with component tag: @")) {
throw new IllegalStateException("Unexpected type: " + e.foundType());
}
} else {
throw new IllegalStateException(cause);
}
}
}
private static byte[] carrierType() {
return ClassFile.of().build(ClassDesc.of("sample", "Carrier"), clb -> {
clb.withSuperclass(CD_Object);
var badAnnotationArray = AnnotationValue.ofArray(AnnotationValue.ofAnnotation(
java.lang.classfile.Annotation.of(
NoAnnotation.class.describeConstable().orElseThrow()
)));
clb.with(RuntimeVisibleAnnotationsAttribute.of(
java.lang.classfile.Annotation.of(ClassDesc.of("sample", "Host"),
AnnotationElement.of("value", badAnnotationArray)
)
));
});
}
private static byte[] annotationType() {
return ClassFile.of().build(ClassDesc.of("sample", "Host"), clb -> {
clb.withSuperclass(CD_Object);
clb.withInterfaceSymbols(Annotation.class.describeConstable().orElseThrow());
clb.withFlags(AccessFlag.PUBLIC, AccessFlag.ABSTRACT, AccessFlag.INTERFACE,
AccessFlag.ANNOTATION);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
java.lang.classfile.Annotation.of(
Retention.class.describeConstable().orElseThrow(),
AnnotationElement.of("value", AnnotationValue.of(RetentionPolicy.RUNTIME))
)
));
clb.withMethod("value", MethodTypeDesc.of(NoAnnotation[].class.describeConstable()
.orElseThrow()), ACC_PUBLIC | ACC_ABSTRACT, mb -> {});
});
}
public interface NoAnnotation { }
public static class ByteArrayClassLoader extends ClassLoader {
public ByteArrayClassLoader(ClassLoader parent) {
super(parent);
}
void init(byte[] annotationType, byte[] carrierType) {
defineClass("sample.Host", annotationType, 0, annotationType.length);
defineClass("sample.Carrier", carrierType, 0, carrierType.length);
}
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2020, 2024, 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 8228988 8266598
* @summary An enumeration-typed property of an annotation that is represented as an
* incompatible property of another type should yield an AnnotationTypeMismatchException.
* @run main EnumTypeMismatchTest
*/
import java.lang.annotation.AnnotationTypeMismatchException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.classfile.Annotation;
import java.lang.classfile.AnnotationElement;
import java.lang.classfile.AnnotationValue;
import java.lang.classfile.ClassFile;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.lang.constant.ClassDesc;
import static java.lang.constant.ConstantDescs.CD_Object;
public class EnumTypeMismatchTest {
public static void main(String[] args) throws Exception {
/*
* @AnAnnotation(value = @AnAnnotation) // would now be: value = AnEnum.VALUE
* class Carrier { }
*/
ClassDesc anAnnotationDesc = AnAnnotation.class.describeConstable().orElseThrow();
byte[] b = ClassFile.of().build(ClassDesc.of("sample", "Carrier"), clb -> {
clb.withSuperclass(CD_Object);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(anAnnotationDesc, AnnotationElement.of("value",
AnnotationValue.ofAnnotation(Annotation.of(anAnnotationDesc))))
));
});
ByteArrayClassLoader cl = new ByteArrayClassLoader(EnumTypeMismatchTest.class.getClassLoader());
cl.init(b);
AnAnnotation sample = cl.loadClass("sample.Carrier").getAnnotation(AnAnnotation.class);
try {
AnEnum value = sample.value();
throw new IllegalStateException("Found value: " + value);
} catch (AnnotationTypeMismatchException e) {
if (!e.element().getName().equals("value")) {
throw new IllegalStateException("Unexpected element: " + e.element());
} else if (!e.foundType().equals("@" + AnAnnotation.class.getCanonicalName() + "(" + AnEnum.VALUE.name() + ")")) {
throw new IllegalStateException("Unexpected type: " + e.foundType());
}
}
}
public enum AnEnum {
VALUE
}
@Retention(RetentionPolicy.RUNTIME)
public @interface AnAnnotation {
AnEnum value() default AnEnum.VALUE;
}
public static class ByteArrayClassLoader extends ClassLoader {
public ByteArrayClassLoader(ClassLoader parent) {
super(parent);
}
void init(byte[] b) {
defineClass("sample.Carrier", b, 0, b.length);
}
}
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2004, 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 6179014
* @summary AnnotationTypeMismatchException.foundType method shouldn't loop.
* @author Scott Seligman
* @run main/timeout=30 FoundType
*/
import java.lang.annotation.*;
public class FoundType {
private static final String TYPE = "a.halting.Problem";
public static void main(String[] args) {
AnnotationTypeMismatchException ex =
new AnnotationTypeMismatchException(null, TYPE);
if (!TYPE.equals(ex.foundType()))
throw new Error();
}
}

View file

@ -0,0 +1,419 @@
/*
* Copyright (c) 2016, 2024, 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.
*/
/*
* Create class file using ASM, slightly modified the ASMifier output
*/
import org.testng.Assert;
import org.testng.annotations.Test;
import java.lang.annotation.Annotation;
import java.lang.annotation.AnnotationFormatError;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/*
* @test
* @bug 8158510
* @summary Verify valid annotation
* @modules java.base/sun.reflect.annotation
* @clean AnnotationWithVoidReturn AnnotationWithParameter
* AnnotationWithExtraInterface AnnotationWithException
* AnnotationWithHashCode AnnotationWithDefaultMember
* AnnotationWithoutAnnotationAccessModifier HolderX
* @compile -XDignore.symbol.file ClassFileGenerator.java GoodAnnotation.java
* @run main ClassFileGenerator
* @run testng AnnotationVerifier
*/
public class AnnotationVerifier {
//=======================================================
// GoodAnnotation...
@GoodAnnotation
static class HolderA {
}
@Test
public void holderA_goodAnnotation() {
testGetAnnotation(HolderA.class, GoodAnnotation.class, true);
}
@Test
public void holderA_annotations() {
testGetAnnotations(HolderA.class, GoodAnnotation.class);
}
//=======================================================
// AnnotationWithParameter...
/*
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithParameter {
int m(int x) default -1;
}
*/
@GoodAnnotation
@AnnotationWithParameter
static class HolderB {
}
@Test
public void holderB_annotationWithParameter() {
testGetAnnotation(HolderB.class, AnnotationWithParameter.class, false);
}
@Test
public void holderB_goodAnnotation() {
testGetAnnotation(HolderB.class, GoodAnnotation.class, true);
}
@Test
public void holderB_annotations() {
testGetAnnotations(HolderB.class, GoodAnnotation.class);
}
//=======================================================
// AnnotationWithVoidReturn...
/*
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithVoidReturn {
void m() default 1;
}
*/
@GoodAnnotation
@AnnotationWithVoidReturn
static class HolderC {
}
@Test(expectedExceptions = AnnotationFormatError.class)
public void holderC_annotationWithVoidReturn() {
testGetAnnotation(HolderC.class, AnnotationWithVoidReturn.class, false);
}
@Test(expectedExceptions = AnnotationFormatError.class)
public void holderC_goodAnnotation() {
testGetAnnotation(HolderC.class, GoodAnnotation.class, false);
}
@Test(expectedExceptions = AnnotationFormatError.class)
public void holderC_annotations() {
testGetAnnotations(HolderC.class);
}
//=======================================================
// AnnotationWithExtraInterface...
/*
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithExtraInterface extends java.io.Serializable {
int m() default 1;
}
*/
@GoodAnnotation
@AnnotationWithExtraInterface
static class HolderD {
}
@Test(expectedExceptions = AnnotationFormatError.class)
public void holderD_annotationWithExtraInterface() {
testGetAnnotation(HolderD.class, AnnotationWithExtraInterface.class, false);
}
@Test(expectedExceptions = AnnotationFormatError.class)
public void holderD_goodAnnotation() {
testGetAnnotation(HolderD.class, GoodAnnotation.class, false);
}
@Test(expectedExceptions = AnnotationFormatError.class)
public void holderD_annotations() {
testGetAnnotations(HolderD.class);
}
//=======================================================
// AnnotationWithException...
/*
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithException {
int m() throws Exception default 1;
}
*/
@GoodAnnotation
@AnnotationWithException
static class HolderE {
}
@AnnotationWithException
static class HolderE2 {
}
@Test
public void holderE_annotationWithException() {
testGetAnnotation(HolderE.class, AnnotationWithException.class, true);
}
@Test
public void holderE_goodAnnotation() {
testGetAnnotation(HolderE.class, GoodAnnotation.class, true);
}
@Test
public void holderE_annotations() {
testGetAnnotations(HolderE.class, GoodAnnotation.class, AnnotationWithException.class);
}
@Test(expectedExceptions = AnnotationFormatError.class)
public void holderE_annotationWithException_equals() {
AnnotationWithException ann1, ann2;
try {
ann1 = HolderE.class.getAnnotation(AnnotationWithException.class);
ann2 = HolderE2.class.getAnnotation(AnnotationWithException.class);
} catch (Throwable t) {
throw new AssertionError("Unexpected exception", t);
}
Assert.assertNotNull(ann1);
Assert.assertNotNull(ann2);
testEquals(ann1, ann2, true); // this throws AnnotationFormatError
}
//=======================================================
// AnnotationWithHashCode...
/*
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithHashCode {
int hashCode() default 1;
}
*/
@GoodAnnotation
@AnnotationWithHashCode
static class HolderF {
}
@AnnotationWithHashCode
static class HolderF2 {
}
@Test
public void holderF_annotationWithHashCode() {
testGetAnnotation(HolderF.class, AnnotationWithHashCode.class, true);
}
@Test
public void holderF_goodAnnotation() {
testGetAnnotation(HolderF.class, GoodAnnotation.class, true);
}
@Test
public void holderF_annotations() {
testGetAnnotations(HolderF.class, GoodAnnotation.class, AnnotationWithHashCode.class);
}
@Test(expectedExceptions = AnnotationFormatError.class)
public void holderF_annotationWithHashCode_equals() {
AnnotationWithHashCode ann1, ann2;
try {
ann1 = HolderF.class.getAnnotation(AnnotationWithHashCode.class);
ann2 = HolderF2.class.getAnnotation(AnnotationWithHashCode.class);
} catch (Throwable t) {
throw new AssertionError("Unexpected exception", t);
}
Assert.assertNotNull(ann1);
Assert.assertNotNull(ann2);
testEquals(ann1, ann2, true); // this throws AnnotationFormatError
}
//=======================================================
// AnnotationWithDefaultMember...
/*
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithDefaultMember {
int m() default 1;
default int d() default 2 { return 2; }
}
*/
@GoodAnnotation
@AnnotationWithDefaultMember
static class HolderG {
}
@AnnotationWithDefaultMember
static class HolderG2 {
}
@Test
public void holderG_annotationWithDefaultMember() {
testGetAnnotation(HolderG.class, AnnotationWithDefaultMember.class, true);
}
@Test
public void holderG_goodAnnotation() {
testGetAnnotation(HolderG.class, GoodAnnotation.class, true);
}
@Test
public void holderG_annotations() {
testGetAnnotations(HolderG.class, GoodAnnotation.class, AnnotationWithDefaultMember.class);
}
@Test(expectedExceptions = AnnotationFormatError.class)
public void holderG_annotationWithDefaultMember_equals() {
AnnotationWithDefaultMember ann1, ann2;
try {
ann1 = HolderG.class.getAnnotation(AnnotationWithDefaultMember.class);
ann2 = HolderG2.class.getAnnotation(AnnotationWithDefaultMember.class);
} catch (Throwable t) {
throw new AssertionError("Unexpected exception", t);
}
Assert.assertNotNull(ann1);
Assert.assertNotNull(ann2);
testEquals(ann1, ann2, true); // this throws AnnotationFormatError
}
//=======================================================
// AnnotationWithoutAnnotationAccessModifier...
/*
@Retention(RetentionPolicy.RUNTIME)
public interface AnnotationWithoutAnnotationAccessModifier extends Annotation {
int m() default 1;
}
@GoodAnnotation
@AnnotationWithoutAnnotationAccessModifier
static class HolderX {
}
*/
@Test
public void holderX_annotationWithoutAnnotationAccessModifier() {
testGetAnnotation(HolderX.class, AnnotationWithoutAnnotationAccessModifier.class, false);
}
@Test
public void holderX_goodAnnotation() {
testGetAnnotation(HolderX.class, GoodAnnotation.class, true);
}
@Test
public void holderX_annotations() {
testGetAnnotations(HolderX.class, GoodAnnotation.class);
}
//=======================================================
// utils
//
private static void testGetAnnotation(Class<?> holderClass,
Class<? extends Annotation> annType,
boolean expectedPresent) {
Object result = null;
try {
try {
result = holderClass.getAnnotation(annType);
if (expectedPresent != (result != null)) {
throw new AssertionError("Expected " +
(expectedPresent ? "non-null" : "null") +
" result, but got: " + result);
}
} catch (Throwable t) {
result = t;
throw t;
}
} finally {
System.out.println("\n" +
holderClass.getSimpleName() +
".class.getAnnotation(" +
annType.getSimpleName() +
".class) = " +
result);
}
}
private static void testGetAnnotations(Class<?> holderClass,
Class<? extends Annotation> ... expectedTypes) {
Object result = null;
try {
try {
Annotation[] anns = holderClass.getAnnotations();
Set<Class<? extends Annotation>> gotTypes =
Stream.of(anns)
.map(Annotation::annotationType)
.collect(Collectors.toSet());
Set<Class<? extends Annotation>> expTypes =
Stream.of(expectedTypes)
.collect(Collectors.toSet());
if (!expTypes.equals(gotTypes)) {
throw new AssertionError("Expected annotation types: " + expTypes +
" but got: " + Arrays.toString(anns));
}
result = Arrays.toString(anns);
} catch (Throwable t) {
result = t;
throw t;
}
} finally {
System.out.println("\n" +
holderClass.getSimpleName() +
".class.getAnnotations() = " +
result);
}
}
private static void testEquals(Annotation ann1, Annotation ann2, boolean expectedEquals) {
Object result = null;
try {
try {
boolean gotEquals = ann1.equals(ann2);
Assert.assertEquals(gotEquals, expectedEquals);
result = gotEquals;
} catch (Throwable t) {
result = t;
throw t;
}
} finally {
System.out.println("\n" + ann1 + ".equals(" + ann2 + ") = " + result);
}
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2016, 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 8147585
* @summary Check Annotation with Lambda, with or without parameter
* @run testng AnnotationWithLambda
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.function.Consumer;
import org.testng.annotations.*;
import static org.testng.Assert.*;
public class AnnotationWithLambda {
@Test
public void testAnnotationWithLambda() {
Method[] methods = AnnotationWithLambda.MethodsWithAnnotations.class.getDeclaredMethods();
for (Method method : methods) {
assertTrue((method.isAnnotationPresent(LambdaWithParameter.class)) &&
(method.isAnnotationPresent(LambdaWithoutParameter.class)));
}
}
static class MethodsWithAnnotations {
@LambdaWithParameter
@LambdaWithoutParameter
public void testAnnotationLambda() {
}
}
}
@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface LambdaWithParameter {
Consumer<Integer> f1 = a -> {
System.out.println("lambda has parameter");
};
}
@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface LambdaWithoutParameter {
Runnable r = () -> System.out.println("lambda without parameter");
}

View file

@ -0,0 +1,212 @@
/*
* 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 8011940
* @summary Test inheritance, order and class redefinition behaviour of RUNTIME
* class annotations
* @author plevart
* @modules java.base/java.lang:open
* java.base/sun.reflect.annotation
*/
import sun.reflect.annotation.AnnotationParser;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.StringJoiner;
public class AnnotationsInheritanceOrderRedefinitionTest {
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface Ann1 {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface Ann2 {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface Ann3 {
String value();
}
@Ann1("A")
@Ann2("A")
static class A {}
@Ann3("B")
static class B extends A {}
@Ann1("C")
@Ann3("C")
static class C extends B {}
public static void main(String[] args) {
StringBuilder msgs = new StringBuilder();
boolean ok = true;
ok &= annotationsEqual(msgs, A.class, true,
ann(Ann1.class, "A"), ann(Ann2.class, "A"));
ok &= annotationsEqual(msgs, A.class, false,
ann(Ann1.class, "A"), ann(Ann2.class, "A"));
ok &= annotationsEqual(msgs, B.class, true,
ann(Ann3.class, "B"));
ok &= annotationsEqual(msgs, B.class, false,
ann(Ann1.class, "A"), ann(Ann2.class, "A"), ann(Ann3.class, "B"));
ok &= annotationsEqual(msgs, C.class, true,
ann(Ann1.class, "C"), ann(Ann3.class, "C"));
ok &= annotationsEqual(msgs, C.class, false,
ann(Ann1.class, "C"), ann(Ann2.class, "A"), ann(Ann3.class, "C"));
Annotation[] declaredAnnotatiosA = A.class.getDeclaredAnnotations();
Annotation[] annotationsA = A.class.getAnnotations();
Annotation[] declaredAnnotatiosB = B.class.getDeclaredAnnotations();
Annotation[] annotationsB = B.class.getAnnotations();
Annotation[] declaredAnnotatiosC = C.class.getDeclaredAnnotations();
Annotation[] annotationsC = C.class.getAnnotations();
incrementClassRedefinedCount(A.class);
incrementClassRedefinedCount(B.class);
incrementClassRedefinedCount(C.class);
ok &= annotationsEqualButNotSame(msgs, A.class, true, declaredAnnotatiosA);
ok &= annotationsEqualButNotSame(msgs, A.class, false, annotationsA);
ok &= annotationsEqualButNotSame(msgs, B.class, true, declaredAnnotatiosB);
ok &= annotationsEqualButNotSame(msgs, B.class, false, annotationsB);
ok &= annotationsEqualButNotSame(msgs, C.class, true, declaredAnnotatiosC);
ok &= annotationsEqualButNotSame(msgs, C.class, false, annotationsC);
if (!ok) {
throw new RuntimeException("test failure\n" + msgs);
}
}
// utility methods
private static boolean annotationsEqualButNotSame(StringBuilder msgs,
Class<?> declaringClass, boolean declaredOnly, Annotation[] oldAnns) {
if (!annotationsEqual(msgs, declaringClass, declaredOnly, oldAnns)) {
return false;
}
Annotation[] anns = declaredOnly
? declaringClass.getDeclaredAnnotations()
: declaringClass.getAnnotations();
List<Annotation> sameAnns = new ArrayList<>();
for (int i = 0; i < anns.length; i++) {
if (anns[i] == oldAnns[i]) {
sameAnns.add(anns[i]);
}
}
if (!sameAnns.isEmpty()) {
msgs.append(declaredOnly ? "declared " : "").append("annotations for ")
.append(declaringClass.getSimpleName())
.append(" not re-parsed after class redefinition: ")
.append(toSimpleString(sameAnns)).append("\n");
return false;
} else {
return true;
}
}
private static boolean annotationsEqual(StringBuilder msgs,
Class<?> declaringClass, boolean declaredOnly, Annotation... expectedAnns) {
Annotation[] anns = declaredOnly
? declaringClass.getDeclaredAnnotations()
: declaringClass.getAnnotations();
if (!Arrays.equals(anns, expectedAnns)) {
msgs.append(declaredOnly ? "declared " : "").append("annotations for ")
.append(declaringClass.getSimpleName()).append(" are: ")
.append(toSimpleString(anns)).append(", expected: ")
.append(toSimpleString(expectedAnns)).append("\n");
return false;
} else {
return true;
}
}
private static Annotation ann(Class<? extends Annotation> annotationType,
Object value) {
return AnnotationParser.annotationForMap(annotationType,
Collections.singletonMap("value", value));
}
private static String toSimpleString(List<Annotation> anns) {
return toSimpleString(anns.toArray(new Annotation[anns.size()]));
}
private static String toSimpleString(Annotation[] anns) {
StringJoiner joiner = new StringJoiner(", ");
for (Annotation ann : anns) {
joiner.add(toSimpleString(ann));
}
return joiner.toString();
}
private static String toSimpleString(Annotation ann) {
Class<? extends Annotation> annotationType = ann.annotationType();
Object value;
try {
value = annotationType.getDeclaredMethod("value").invoke(ann);
} catch (IllegalAccessException | InvocationTargetException
| NoSuchMethodException e) {
throw new RuntimeException(e);
}
return "@" + annotationType.getSimpleName() + "(" + value + ")";
}
private static final Field classRedefinedCountField;
static {
try {
classRedefinedCountField = Class.class.getDeclaredField("classRedefinedCount");
classRedefinedCountField.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new Error(e);
}
}
private static void incrementClassRedefinedCount(Class<?> clazz) {
try {
classRedefinedCountField.set(clazz,
((Integer) classRedefinedCountField.get(clazz)) + 1);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,285 @@
/*
* Copyright (c) 2016, 2024, 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.
*/
/*
* Create class file using Class-File API, slightly modified the ASMifier output
*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.classfile.Annotation;
import java.lang.classfile.AnnotationElement;
import java.lang.classfile.AnnotationValue;
import java.lang.classfile.ClassFile;
import java.lang.classfile.attribute.AnnotationDefaultAttribute;
import java.lang.classfile.attribute.ExceptionsAttribute;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.lang.reflect.AccessFlag;
import static java.lang.classfile.ClassFile.ACC_ABSTRACT;
import static java.lang.classfile.ClassFile.ACC_PUBLIC;
import static java.lang.constant.ConstantDescs.CD_Exception;
import static java.lang.constant.ConstantDescs.CD_Object;
import static java.lang.constant.ConstantDescs.CD_int;
import static java.lang.constant.ConstantDescs.MTD_void;
import static java.lang.reflect.AccessFlag.ABSTRACT;
import static java.lang.reflect.AccessFlag.INTERFACE;
import static java.lang.reflect.AccessFlag.PUBLIC;
public class ClassFileGenerator {
private static final ClassDesc CD_Annotation = java.lang.annotation.Annotation.class.describeConstable().orElseThrow();
private static final ClassDesc CD_Retention = Retention.class.describeConstable().orElseThrow();
public static void main(String... args) throws Exception {
classFileWriter("AnnotationWithVoidReturn.class", AnnotationWithVoidReturnDump.dump());
classFileWriter("AnnotationWithParameter.class", AnnotationWithParameterDump.dump());
classFileWriter("AnnotationWithExtraInterface.class", AnnotationWithExtraInterfaceDump.dump());
classFileWriter("AnnotationWithException.class", AnnotationWithExceptionDump.dump());
classFileWriter("AnnotationWithHashCode.class", AnnotationWithHashCodeDump.dump());
classFileWriter("AnnotationWithDefaultMember.class", AnnotationWithDefaultMemberDump.dump());
classFileWriter("AnnotationWithoutAnnotationAccessModifier.class",
AnnotationWithoutAnnotationAccessModifierDump.dump());
classFileWriter("HolderX.class", HolderXDump.dump());
}
private static void classFileWriter(String name, byte[] contents) throws IOException {
try (FileOutputStream fos = new FileOutputStream(new File(System.getProperty("test.classes"),
name))) {
fos.write(contents);
}
}
/* Following code creates equivalent classfile, which is not allowed by javac:
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithVoidReturn {
void m() default 1;
}
*/
private static class AnnotationWithVoidReturnDump {
public static byte[] dump() {
return ClassFile.of().build(ClassDesc.of("AnnotationWithVoidReturn"), clb -> {
clb.withSuperclass(CD_Object);
clb.withInterfaceSymbols(CD_Annotation);
clb.withFlags(PUBLIC, AccessFlag.ANNOTATION, ABSTRACT, AccessFlag.INTERFACE);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(CD_Retention, AnnotationElement.of("value",
AnnotationValue.of(RetentionPolicy.RUNTIME)))
));
clb.withMethod("m", MTD_void, ACC_PUBLIC | ACC_ABSTRACT,
mb -> mb.with(AnnotationDefaultAttribute.of(AnnotationValue.ofInt(1))));
});
}
}
/* Following code creates equivalent classfile, which is not allowed by javac:
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithParameter {
int m(int x) default -1;
}
*/
private static class AnnotationWithParameterDump {
public static byte[] dump() {
return ClassFile.of().build(ClassDesc.of("AnnotationWithParameter"), clb -> {
clb.withSuperclass(CD_Object);
clb.withInterfaceSymbols(CD_Annotation);
clb.withFlags(PUBLIC, AccessFlag.ANNOTATION, ABSTRACT, AccessFlag.INTERFACE);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(CD_Retention, AnnotationElement.of("value",
AnnotationValue.of(RetentionPolicy.RUNTIME)))
));
clb.withMethod("m", MethodTypeDesc.of(CD_int, CD_int), ACC_PUBLIC | ACC_ABSTRACT,
mb -> mb.with(AnnotationDefaultAttribute.of(AnnotationValue.ofInt(-1))));
});
}
}
/* Following code creates equivalent classfile, which is not allowed by javac:
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithExtraInterface extends java.io.Serializable {
int m() default 1;
}
*/
private static class AnnotationWithExtraInterfaceDump {
public static byte[] dump() {
return ClassFile.of().build(ClassDesc.of("AnnotationWithExtraInterface"), clb -> {
clb.withSuperclass(CD_Object);
clb.withInterfaceSymbols(CD_Annotation, Serializable.class.describeConstable().orElseThrow());
clb.withFlags(PUBLIC, AccessFlag.ANNOTATION, ABSTRACT, AccessFlag.INTERFACE);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(CD_Retention, AnnotationElement.of("value",
AnnotationValue.of(RetentionPolicy.RUNTIME)))
));
clb.withMethod("m", MethodTypeDesc.of(CD_int), ACC_PUBLIC | ACC_ABSTRACT,
mb -> mb.with(AnnotationDefaultAttribute.of(AnnotationValue.ofInt(1))));
});
}
}
/* Following code creates equivalent classfile, which is not allowed by javac:
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithException {
int m() throws Exception default 1;
}
*/
private static class AnnotationWithExceptionDump {
public static byte[] dump() {
return ClassFile.of().build(ClassDesc.of("AnnotationWithException"), clb -> {
clb.withSuperclass(CD_Object);
clb.withInterfaceSymbols(CD_Annotation);
clb.withFlags(PUBLIC, AccessFlag.ANNOTATION, ABSTRACT, AccessFlag.INTERFACE);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(CD_Retention, AnnotationElement.of("value",
AnnotationValue.of(RetentionPolicy.RUNTIME)))
));
clb.withMethod("m", MethodTypeDesc.of(CD_int), ACC_PUBLIC | ACC_ABSTRACT, mb -> {
mb.with(AnnotationDefaultAttribute.of(AnnotationValue.ofInt(1)));
mb.with(ExceptionsAttribute.ofSymbols(CD_Exception));
});
});
}
}
/* Following code creates equivalent classfile, which is not allowed by javac:
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithHashCode {
int hashCode() default 1;
}
*/
private static class AnnotationWithHashCodeDump {
public static byte[] dump() {
return ClassFile.of().build(ClassDesc.of("AnnotationWithHashCode"), clb -> {
clb.withSuperclass(CD_Object);
clb.withInterfaceSymbols(CD_Annotation);
clb.withFlags(PUBLIC, AccessFlag.ANNOTATION, ABSTRACT, AccessFlag.INTERFACE);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(CD_Retention, AnnotationElement.of("value",
AnnotationValue.of(RetentionPolicy.RUNTIME)))
));
clb.withMethod("hashCode", MethodTypeDesc.of(CD_int), ACC_PUBLIC | ACC_ABSTRACT,
mb -> mb.with(AnnotationDefaultAttribute.of(AnnotationValue.ofInt(1))));
});
}
}
/* Following code creates equivalent classfile, which is not allowed by javac:
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithDefaultMember {
int m() default 1;
default int d() default 2 { return 2; }
}
*/
private static class AnnotationWithDefaultMemberDump {
public static byte[] dump() throws Exception {
return ClassFile.of().build(ClassDesc.of("AnnotationWithDefaultMember"), clb -> {
clb.withSuperclass(CD_Object);
clb.withInterfaceSymbols(CD_Annotation);
clb.withFlags(PUBLIC, AccessFlag.ANNOTATION, ABSTRACT, AccessFlag.INTERFACE);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(CD_Retention, AnnotationElement.of("value",
AnnotationValue.of(RetentionPolicy.RUNTIME)))
));
clb.withMethod("m", MethodTypeDesc.of(CD_int), ACC_PUBLIC | ACC_ABSTRACT,
mb -> mb.with(AnnotationDefaultAttribute.of(AnnotationValue.ofInt(1))));
clb.withMethod("d", MethodTypeDesc.of(CD_int), ACC_PUBLIC, mb -> {
mb.with(AnnotationDefaultAttribute.of(AnnotationValue.ofInt(2)));
mb.withCode(cob -> {
cob.iconst_2();
cob.ireturn();
});
});
});
}
}
/* Following code creates equivalent classfile, which is not allowed by javac:
@Retention(RetentionPolicy.RUNTIME)
public interface AnnotationWithoutAnnotationAccessModifier extends java.lang.annotation.Annotation {
int m() default 1;
}
*/
private static class AnnotationWithoutAnnotationAccessModifierDump {
public static byte[] dump() {
return ClassFile.of().build(ClassDesc.of("AnnotationWithoutAnnotationAccessModifier"), clb -> {
clb.withSuperclass(CD_Object);
clb.withInterfaceSymbols(CD_Annotation);
clb.withFlags(PUBLIC, /*AccessFlag.ANNOTATION,*/ ABSTRACT, AccessFlag.INTERFACE);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(CD_Retention, AnnotationElement.of("value",
AnnotationValue.of(RetentionPolicy.RUNTIME)))
));
clb.withMethod("m", MethodTypeDesc.of(CD_int), ACC_PUBLIC | ACC_ABSTRACT,
mb -> mb.with(AnnotationDefaultAttribute.of(AnnotationValue.ofInt(1))));
});
}
}
/* Following code creates equivalent classfile, which is not allowed by javac
since AnnotationWithoutAnnotationAccessModifier is not marked with ACC_ANNOTATION:
@GoodAnnotation
@AnnotationWithoutAnnotationAccessModifier
public interface HolderX {
}
*/
private static class HolderXDump {
public static byte[] dump() {
return ClassFile.of().build(ClassDesc.of("HolderX"), clb -> {
clb.withSuperclass(CD_Object);
clb.withFlags(PUBLIC, ABSTRACT, INTERFACE);
clb.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(ClassDesc.of("GoodAnnotation")),
Annotation.of(ClassDesc.of("ClassFileGenerator$AnnotationWithoutAnnotationAccessModifier"))
));
});
}
}
}

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2024, 2025, 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 8345614 8350704
* @summary Ensure behavior with duplicated annotations - class, method, or
* field fails fast on duplicate annotations, but parameter allows them
* @library /test/lib
* @run junit DuplicateAnnotationsTest
*/
import java.io.IOException;
import java.lang.annotation.AnnotationFormatError;
import java.lang.classfile.*;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.lang.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute;
import java.lang.constant.ClassDesc;
import java.lang.reflect.AnnotatedElement;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import jdk.test.lib.ByteCodeLoader;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.function.Executable;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.*;
class DuplicateAnnotationsTest {
static ClassModel cm;
@BeforeAll
static void setup() throws IOException {
Path annoDuplicatedClass = Path.of(System.getProperty("test.classes")).resolve("AnnotationDuplicated.class");
cm = ClassFile.of().parse(annoDuplicatedClass);
}
interface Extractor {
AnnotatedElement find(Class<?> cl) throws ReflectiveOperationException;
}
// Compiler hint
static Extractor extract(Extractor e) {
return e;
}
static Arguments[] arguments() {
Annotation annotationOne = Annotation.of(ClassDesc.of("java.lang.Deprecated"), AnnotationElement.ofBoolean("forRemoval", true));
Annotation annotationTwo = Annotation.of(ClassDesc.of("java.lang.Deprecated"), AnnotationElement.ofString("since", "24"));
RuntimeVisibleAnnotationsAttribute rvaa = RuntimeVisibleAnnotationsAttribute.of(
List.of(annotationOne, annotationTwo)
);
return new Arguments[]{
Arguments.of(
"class", true,
ClassTransform.endHandler(cob -> cob.with(rvaa)),
extract(c -> c)
),
Arguments.of(
"field", true,
ClassTransform.transformingFields(FieldTransform.endHandler(fb -> fb.with(rvaa))),
extract(c -> c.getDeclaredField("field"))
),
Arguments.of(
"method", true,
ClassTransform.transformingMethods(MethodTransform.endHandler(mb -> mb.with(rvaa))),
extract(c -> c.getDeclaredConstructor(int.class))
),
Arguments.of(
"parameter", false, // Surprisingly, parameters always allowed duplicate annotations
ClassTransform.transformingMethods(MethodTransform.endHandler(mb -> mb.with(
RuntimeVisibleParameterAnnotationsAttribute.of(
List.of(List.of(annotationOne, annotationTwo))
)
))),
extract(c -> c.getDeclaredConstructor(int.class).getParameters()[0])
),
};
}
/**
* A test case represents a declaration that can be annotated.
* Different declarations have different behaviors when multiple annotations
* of the same interface are present (without a container annotation).
*
* @param caseName the type of declaration, for pretty printing in JUnit
* @param fails whether this case should fail upon encountering duplicate annotations
* @param ct transform to install duplicate annotations on the specific declaration
* @param extractor function to access the AnnotatedElement representing that declaration
*/
@MethodSource("arguments")
@ParameterizedTest
void test(String caseName, boolean fails, ClassTransform ct, Extractor extractor) throws IOException, ReflectiveOperationException {
var clazz = ByteCodeLoader.load("AnnotationDuplicated", ClassFile.of().transformClass(cm, ct));
var element = assertDoesNotThrow(() -> extractor.find(clazz));
Executable exec = () -> element.getAnnotation(Deprecated.class);
if (fails) {
var ex = assertThrows(AnnotationFormatError.class, exec, "no duplicate annotation access");
assertTrue(ex.getMessage().contains("Deprecated"), () -> "missing problematic annotation: " + ex.getMessage());
assertTrue(ex.getMessage().contains("AnnotationDuplicated"), () -> "missing container class: " + ex.getMessage());
} else {
assertDoesNotThrow(exec, "obtaining duplicate annotations should be fine");
assertEquals(2, Arrays.stream(element.getAnnotations())
.filter(anno -> anno instanceof Deprecated)
.count());
}
}
}
// Duplicate annotations on class, field, method (constructor), method parameter
class AnnotationDuplicated {
int field;
AnnotationDuplicated(int arg) {
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021, 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 8263763
* @summary Check that annotations on an enum constructor are indexed correctly.
*/
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class EnumConstructorAnnotation {
public static void main(String[] args) {
Constructor<?> c = SampleEnum.class.getDeclaredConstructors()[0];
Annotation[] a1 = c.getParameters()[2].getAnnotations(), a2 = c.getParameterAnnotations()[2];
for (Annotation[] a : Arrays.asList(a1, a2)) {
if (a.length != 1) {
throw new RuntimeException("Unexpected length " + a.length);
} else if (a[0].annotationType() != SampleAnnotation.class) {
throw new RuntimeException("Unexpected type " + a[0]);
}
}
}
enum SampleEnum {
INSTANCE("foo");
SampleEnum(@SampleAnnotation String value) { }
}
@Retention(RetentionPolicy.RUNTIME)
@interface SampleAnnotation { }
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2016, 2021, 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 8071859 8169629
* @summary Check annotation equality behavior against the invocation handler
* @compile --release 8 EqualityTest.java
* @run main EqualityTest
* @compile EqualityTest.java
* @run main EqualityTest
*/
import java.lang.annotation.*;
import java.lang.reflect.*;
@TestAnnotation
public class EqualityTest {
public static void main(String... args) throws Exception {
TestAnnotation annotation =
EqualityTest.class.getAnnotation(TestAnnotation.class);
InvocationHandler handler = Proxy.getInvocationHandler(annotation);
testEquality(annotation, handler, false);
testEquality(annotation, annotation, true);
testEquality(handler, handler, true);
testEquality(annotation, AnnotationHost.class.getAnnotation(TestAnnotation.class), true);
}
private static void testEquality(Object a, Object b, boolean expected) {
boolean result = a.equals(b);
if (result != b.equals(a) || result != expected)
throw new RuntimeException("Unexpected result");
}
@TestAnnotation
private static class AnnotationHost {}
}
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {
// Trigger creation of synthetic method to initialize r.
public static final Runnable r = () -> {};
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2016, 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.
*/
@DangerousAnnotation(utopia=Utopia.BRIGADOON,
thirtyTwoBitsAreNotEnough=42,
classy=Fleeting.class,
classies={Object.class, int.class},
moreClassies={})
public class AnnotationHost {}

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2016, 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 5040830
* @summary Verify information annotation strings with exception proxies
* @compile -sourcepath version1 version1/Fleeting.java version1/Utopia.java version1/DangerousAnnotation.java
* @compile AnnotationHost.java
* @build ExceptionalToStringTest
* @run main ExceptionalToStringTest
* @clean Utopia DangerousAnnotation
* @compile -sourcepath version2 -implicit:none version2/Utopia.java
* @compile -sourcepath version2 -implicit:none version2/DangerousAnnotation.java
* @clean Fleeting
* @run main ExceptionalToStringTest
*/
/**
* There are three potential exception conditions which can occur
* reading annotations:
*
* EnumConstantNotPresentException - "Thrown when an application tries
* to access an enum constant by name and the enum type contains no
* constant with the specified name."
*
* AnnotationTypeMismatchException - "Thrown to indicate that a
* program has attempted to access an element of an annotation whose
* type has changed after the annotation was compiled (or serialized)"
*
* TypeNotPresentException - "Thrown when an application tries to
* access a type using a string representing the type's name, but no
* definition for the type with the specified name can be found."
*
* The test reads an annotation, DangerousAnnotation, which can
* display all three pathologies. The pathologies are <em>not</em>
* present when the version1 sources are used but are present with the
* version2 sources. The version2 sources remove an enum constant
* (EnumConstantNotPresentException), change the return type of an
* annotation method (AnnotationTypeMismatchException), and remove a
* type whose Class literal is referenced (TypeNotPresentException).
*/
public class ExceptionalToStringTest {
public static void main(String... args) {
String annotationAsString = AnnotationHost.class.getAnnotation(DangerousAnnotation.class).toString();
// Verify no occurrence of "ExceptionProxy" in the string.
if (annotationAsString.indexOf("ExceptionProxy") != -1) {
throw new RuntimeException();
}
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2016, 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.
*/
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface DangerousAnnotation {
Utopia utopia();
int thirtyTwoBitsAreNotEnough();
Class<?> classy();
Class<?>[] classies();
Class<?>[] moreClassies();
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2016, 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.
*/
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface Fleeting {
int value();
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2016, 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.
*/
public enum Utopia {
SHANGRI_LA,
BRIGADOON; // Only there one day out of every 100 years.
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2016, 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.
*/
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface DangerousAnnotation {
Utopia utopia();
long thirtyTwoBitsAreNotEnough();
Class<?> classy();
Class<?>[] classies();
Class<?>[] moreClassies();
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2016, 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.
*/
public enum Utopia {
SHANGRI_LA;
//BRIGADOON -- Only there one day out of every 100 years.
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2017, 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.
*/
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Simple conforming runtime annotation.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface GoodAnnotation {}

View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2004, 2025, 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 5040740
* @summary annotations cause memory leak
* @library /test/lib
* @build jdk.test.lib.process.*
* @run testng/timeout=480 LoaderLeakTest
*/
import jdk.test.lib.Utils;
import jdk.test.lib.process.ProcessTools;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.FileInputStream;
import java.lang.annotation.Retention;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.nio.file.*;
import java.util.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
public class LoaderLeakTest {
@Test
public void testWithoutReadingAnnotations() throws Throwable {
runJavaProcessExpectSuccessExitCode("Main");
}
@Test
public void testWithReadingAnnotations() throws Throwable {
runJavaProcessExpectSuccessExitCode("Main", "foo");
}
private void runJavaProcessExpectSuccessExitCode(String ... command) throws Throwable {
var processBuilder = ProcessTools.createTestJavaProcessBuilder(command)
.directory(Paths.get(Utils.TEST_CLASSES).toFile());
ProcessTools.executeCommand(processBuilder).shouldHaveExitValue(0);
}
}
class Main {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 100; i++) {
doTest(args.length != 0);
}
}
static void doTest(boolean readAnn) throws Exception {
ClassLoader loader = new SimpleClassLoader();
var c = new WeakReference<Class<?>>(loader.loadClass("C"));
if (c.refersTo(null)) throw new AssertionError("class missing after loadClass");
// c.get() should never return null here since we hold a strong
// reference to the class loader that loaded the class referred by c.
if (c.get().getClassLoader() != loader) throw new AssertionError("wrong classloader");
if (readAnn) System.out.println(c.get().getAnnotations()[0]);
if (c.refersTo(null)) throw new AssertionError("class missing before GC");
System.gc();
System.gc();
if (c.refersTo(null)) throw new AssertionError("class missing after GC but before loader is unreachable");
System.gc();
System.gc();
Reference.reachabilityFence(loader);
loader = null;
// Might require multiple calls to System.gc() for weak-references
// processing to be complete. If the weak-reference is not cleared as
// expected we will hang here until timed out by the test harness.
while (true) {
System.gc();
Thread.sleep(20);
if (c.refersTo(null)) {
break;
}
}
}
}
@Retention(RUNTIME)
@interface A {
B b();
}
@interface B { }
@A(b=@B()) class C { }
class SimpleClassLoader extends ClassLoader {
public SimpleClassLoader() { }
private byte[] getClassImplFromDataBase(String className) {
try {
return Files.readAllBytes(Paths.get(className + ".class"));
} catch (Exception e) {
throw new Error("could not load class " + className, e);
}
}
@Override
public Class<?> loadClass(String className, boolean resolveIt)
throws ClassNotFoundException {
switch (className) {
case "A", "B", "C" -> {
var classData = getClassImplFromDataBase(className);
return defineClass(className, classData, 0, classData.length);
}
}
return super.loadClass(className, resolveIt);
}
}

View file

@ -0,0 +1,118 @@
/*
* Copyright (c) 2024, 2025, 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 8350704
* @summary Test behaviors with malformed annotations (in class files)
* @library /test/lib
* @run junit MalformedAnnotationTest
*/
import jdk.test.lib.ByteCodeLoader;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.classfile.Annotation;
import java.lang.classfile.AnnotationElement;
import java.lang.classfile.AnnotationValue;
import java.lang.classfile.ClassFile;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.lang.constant.ClassDesc;
import java.lang.reflect.GenericSignatureFormatError;
import java.util.Arrays;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
class MalformedAnnotationTest {
/**
* An annotation that has elements of the Class type.
* Useful for checking behavior when the string is not a descriptor string.
*/
@Retention(RetentionPolicy.RUNTIME)
@interface ClassCarrier {
Class<?> value();
}
static Stream<String> badFieldDescriptors() {
return Arrays.stream(new String[] {
"Not a_descriptor",
"()V",
"Ljava/lang/Object",
"Ljava/",
"Ljava/util/Map.Entry;",
"[".repeat(256) + "I",
"Lbad.Name;",
"Lbad[Name;",
"L;",
"L/Missing;",
"Lmissing/;",
});
}
/**
* Ensures bad class descriptors in annotations lead to
* {@link GenericSignatureFormatError} and the error message contains the
* malformed descriptor string.
*/
@ParameterizedTest
@MethodSource("badFieldDescriptors")
void testMalformedClassValue(String badDescString) throws Exception {
var cl = spinClass(badDescString);
var ex = assertThrows(GenericSignatureFormatError.class, () -> cl.getDeclaredAnnotation(ClassCarrier.class));
assertTrue(ex.getMessage().contains(badDescString), () -> "Uninformative error: " + ex);
}
private static Class<?> spinClass(String desc) throws Exception {
var bytes = ClassFile.of().build(ClassDesc.of("Test"), clb -> clb
.with(RuntimeVisibleAnnotationsAttribute.of(
Annotation.of(ClassCarrier.class.describeConstable().orElseThrow(),
AnnotationElement.of("value", AnnotationValue.ofClass(clb
.constantPool().utf8Entry(desc))))
)));
return new ByteCodeLoader("Test", bytes, ClassCarrier.class.getClassLoader()).loadClass("Test");
}
static Stream<String> goodFieldDescriptors() {
return Arrays.stream(new String[] {
"Ljava/lang/Object<*>;", // previously MalformedParameterizedTypeException
"[Ljava/util/Optional<*>;", // previously ClassCastException
"Ljava/util/Map$Entry<**>;", // previously ClassCastException
});
}
@ParameterizedTest
@MethodSource("goodFieldDescriptors")
void testLegalClassValue(String goodDescString) throws Exception {
var cl = spinClass(goodDescString);
var anno = cl.getDeclaredAnnotation(ClassCarrier.class);
assertThrows(TypeNotPresentException.class, anno::value);
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2005, 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.
*/
/**
* Class to have a missing annotation applied for running MissingTest.
*/
@Missing
@Marker
public class A {
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2005, 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.
*/
/**
* Class to have an indirectly missing annotation applied for
* running MisssingTest.
*/
@MissingWrapper(@Missing)
@Marker
public class B {
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2005, 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.
*/
/**
* Class to have a missing annotation applied for running MissingTest.
*/
public class C {
public void method1(@Missing @Marker Object param1) {
return;
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2005, 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.
*/
/**
* Class to have a missing annotation applied for running MissingTest.
*/
public class D {
public void method1(@MissingWrapper(@Missing) @Marker Object param1) {
return;
}
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2005, 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.
*/
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.*;
/**
* A marker annotation. Used so that at least one annotation will be
* present on the classes tested by MissingTest.
*/
@Retention(RUNTIME)
public @interface Marker {}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2005, 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.
*/
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.*;
/**
* The class file for this annotation type is missing when MissingTest
* is run.
*/
@Retention(RUNTIME)
public @interface Missing {}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2018, Google Inc. 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.
*/
/**
* The enum that will be seen at compile-time.
*
* <p>The filename deliberately does not match, since we need to declare two versions of the enum
* for compile-time and runtime.
*/
enum Enum {
ONE,
TWO,
THREE
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2018, Google Inc. 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.
*/
/**
* The enum that will be seen at runtime.
*
* <p>The filename deliberately does not match, since we need to declare two versions of the enum
* for compile-time and runtime.
*/
enum Enum {
ONE
}

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018, Google Inc. 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.
*/
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
/** An annotation that will be missing at runtime. */
@Retention(RUNTIME)
public @interface MissingAnnotation {}

View file

@ -0,0 +1,80 @@
/*
* Copyright (c) 2018, Google Inc. 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.
*/
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/*
* @test
* @bug 7183985
* @summary getAnnotation() should throw NoClassDefFoundError when an annotation class is not
* present at runtime
* @compile MissingAnnotationArrayElementTest.java MissingAnnotation.java
* @clean MissingAnnotation
* @run main MissingAnnotationArrayElementTest
*/
public class MissingAnnotationArrayElementTest {
@Retention(RUNTIME)
@interface AnnotationAnnotation {
MissingAnnotation[] value();
}
@AnnotationAnnotation({@MissingAnnotation, @MissingAnnotation})
static class Test {
void f(@AnnotationAnnotation({@MissingAnnotation, @MissingAnnotation}) int x) {}
Test(@AnnotationAnnotation({@MissingAnnotation, @MissingAnnotation}) int x) {}
}
public static void main(String[] args) throws Exception {
// MissingAnnotation will be absent from the runtime classpath, causing a
// NoClassDefFoundError when AnnotationAnnotation is read (since the type of its value array
// references cannot be completed).
assertThrowsNoClassDefFoundError(
() -> Test.class.getAnnotation(AnnotationAnnotation.class));
Method method = Test.class.getDeclaredMethod("f", int.class);
assertThrowsNoClassDefFoundError(method::getParameterAnnotations);
Constructor constructor = Test.class.getDeclaredConstructor(int.class);
assertThrowsNoClassDefFoundError(constructor::getParameterAnnotations);
}
interface ThrowingRunnable {
void run() throws Exception;
}
static void assertThrowsNoClassDefFoundError(ThrowingRunnable throwingRunnable)
throws Exception {
try {
throwingRunnable.run();
throw new AssertionError("expected exception");
} catch (NoClassDefFoundError expected) {
if (!expected.getMessage().contains("MissingAnnotation")) {
throw expected;
}
}
}
}

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2018, Google Inc. 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.
*/
/** A class that will be missing at runtime. */
public class MissingClass {}

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2018, Google Inc. 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.
*/
/** A class that will be missing at runtime. */
public class MissingClass2 {}

View file

@ -0,0 +1,147 @@
/*
* Copyright (c) 2018, Google Inc. 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.
*/
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.util.Arrays;
/*
* @test
* @bug 7183985
* @summary getAnnotation() throws an ArrayStoreException when the annotation class not present
* @compile MissingClassArrayElementTest.java MissingClass.java MissingClass2.java
* @clean MissingClass MissingClass2
* @run main MissingClassArrayElementTest
*/
public class MissingClassArrayElementTest {
@Retention(RUNTIME)
@interface AnnotationAnnotation {
ClassArrayAnnotation[] value();
}
@Retention(RUNTIME)
@interface ClassArrayAnnotation {
Class<?>[] value();
}
@AnnotationAnnotation({
@ClassArrayAnnotation({MissingClass.class}),
@ClassArrayAnnotation({MissingClass.class, String.class}),
@ClassArrayAnnotation({String.class, MissingClass.class}),
@ClassArrayAnnotation({MissingClass.class, MissingClass2.class}),
@ClassArrayAnnotation({String.class})
})
static class Test {
void f(
@AnnotationAnnotation({
@ClassArrayAnnotation({MissingClass.class, MissingClass.class}),
@ClassArrayAnnotation({Float.class})
})
int x,
@AnnotationAnnotation({@ClassArrayAnnotation({Double.class})}) int y) {}
Test(
@AnnotationAnnotation({
@ClassArrayAnnotation({MissingClass.class, MissingClass.class}),
@ClassArrayAnnotation({Short.class}),
})
int x,
@AnnotationAnnotation({@ClassArrayAnnotation({Character.class})}) int y) {}
}
public static void main(String[] args) throws Exception {
classAnnotationTest();
methodParameterAnnotationsTest();
constructorParameterAnnotationsTest();
}
static void classAnnotationTest() throws Exception {
ClassArrayAnnotation[] outer = Test.class.getAnnotation(AnnotationAnnotation.class).value();
assertMissing(outer[0]);
assertMissing(outer[1]);
assertMissing(outer[2]);
assertMissing(outer[3]);
assertArrayEquals(outer[4].value(), new Class<?>[] {String.class});
}
static void methodParameterAnnotationsTest() throws Exception {
AnnotationAnnotation[] methodParameterAnnotations =
Arrays.stream(
Test.class
.getDeclaredMethod("f", int.class, int.class)
.getParameterAnnotations())
.map(x -> ((AnnotationAnnotation) x[0]))
.toArray(AnnotationAnnotation[]::new);
// The first parameter's annotation contains some well-formed values, and the second
// parameter's
// annotation is well-formed
assertArrayEquals(
methodParameterAnnotations[0].value()[1].value(), new Class<?>[] {Float.class});
assertArrayEquals(
methodParameterAnnotations[1].value()[0].value(), new Class<?>[] {Double.class});
// The first parameter's annotation contains a missing value
assertMissing(methodParameterAnnotations[0].value()[0]);
}
static void constructorParameterAnnotationsTest() throws Exception {
AnnotationAnnotation[] constructorParameterAnnotations =
Arrays.stream(
Test.class
.getDeclaredConstructor(int.class, int.class)
.getParameterAnnotations())
.map(x -> ((AnnotationAnnotation) x[0]))
.toArray(AnnotationAnnotation[]::new);
// The first parameter's annotation contains some well-formed values, and the second
// parameter's
// annotation is well-formed
assertArrayEquals(
constructorParameterAnnotations[0].value()[1].value(),
new Class<?>[] {Short.class});
assertArrayEquals(
constructorParameterAnnotations[1].value()[0].value(),
new Class<?>[] {Character.class});
// The first parameter's annotation contains a missing value
assertMissing(constructorParameterAnnotations[0].value()[0]);
}
static void assertArrayEquals(Object[] actual, Object[] expected) {
if (!Arrays.equals(actual, expected)) {
throw new AssertionError(
"expected: " + Arrays.toString(expected) + ", was: " + Arrays.toString(actual));
}
}
static void assertMissing(ClassArrayAnnotation missing) {
try {
missing.value();
throw new AssertionError("expected exception");
} catch (TypeNotPresentException expected) {
if (!expected.typeName().equals("MissingClass")) {
throw new AssertionError(
"expected TypeNotPresentException: MissingClass", expected);
}
}
}
}

View file

@ -0,0 +1,142 @@
/*
* Copyright (c) 2018, Google Inc. 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.
*/
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.util.Arrays;
/*
* @test
* @bug 7183985
* @summary getAnnotation() throws an ArrayStoreException when the annotation class not present
* @compile MissingEnumArrayElementTest.java EnumToCompileAgainst.java
* @clean Enum
* @compile EnumToRunAgainst.java
* @run main MissingEnumArrayElementTest
*/
public class MissingEnumArrayElementTest {
@Retention(RUNTIME)
@interface AnnotationAnnotation {
EnumArrayAnnotation[] value();
}
@Retention(RUNTIME)
@interface EnumArrayAnnotation {
Enum[] value();
}
@AnnotationAnnotation({
@EnumArrayAnnotation({Enum.TWO}),
@EnumArrayAnnotation({Enum.ONE, Enum.TWO}),
@EnumArrayAnnotation({Enum.TWO, Enum.ONE}),
@EnumArrayAnnotation({Enum.TWO, Enum.THREE}),
@EnumArrayAnnotation({Enum.ONE}),
})
static class Test {
void f(
@AnnotationAnnotation({
@EnumArrayAnnotation({Enum.TWO, Enum.ONE}),
@EnumArrayAnnotation({Enum.ONE})
})
int x,
@AnnotationAnnotation({@EnumArrayAnnotation({Enum.ONE})}) int y) {}
Test(
@AnnotationAnnotation({
@EnumArrayAnnotation({Enum.TWO, Enum.ONE}),
@EnumArrayAnnotation({Enum.ONE})
})
int x,
@AnnotationAnnotation({@EnumArrayAnnotation({Enum.ONE})}) int y) {}
}
public static void main(String[] args) throws Exception {
classAnnotationTest();
methodParameterAnnotationsTest();
constructorParameterAnnotationsTest();
}
static void classAnnotationTest() throws Exception {
EnumArrayAnnotation[] outer = Test.class.getAnnotation(AnnotationAnnotation.class).value();
assertMissing(outer[0]);
assertMissing(outer[1]);
assertMissing(outer[2]);
assertMissing(outer[3]);
assertArrayEquals(outer[4].value(), new Enum[] {Enum.ONE});
}
static void methodParameterAnnotationsTest() throws Exception {
AnnotationAnnotation[] methodParameterAnnotations =
Arrays.stream(
Test.class
.getDeclaredMethod("f", int.class, int.class)
.getParameterAnnotations())
.map(x -> ((AnnotationAnnotation) x[0]))
.toArray(AnnotationAnnotation[]::new);
// The first parameter's annotation contains some well-formed values, and the second
// parameter's
// annotation is well-formed
assertArrayEquals(methodParameterAnnotations[0].value()[1].value(), new Enum[] {Enum.ONE});
assertArrayEquals(methodParameterAnnotations[1].value()[0].value(), new Enum[] {Enum.ONE});
// The first parameter's annotation contains a missing value
assertMissing(methodParameterAnnotations[0].value()[0]);
}
static void constructorParameterAnnotationsTest() throws Exception {
AnnotationAnnotation[] constructorParameterAnnotations =
Arrays.stream(
Test.class
.getDeclaredConstructor(int.class, int.class)
.getParameterAnnotations())
.map(x -> ((AnnotationAnnotation) x[0]))
.toArray(AnnotationAnnotation[]::new);
// The first parameter's annotation contains some well-formed values, and the second
// parameter's
// annotation is well-formed
assertArrayEquals(constructorParameterAnnotations[0].value()[1].value(), new Enum[] {Enum.ONE});
assertArrayEquals(constructorParameterAnnotations[1].value()[0].value(), new Enum[] {Enum.ONE});
// The first parameter's annotation contains a missing value
assertMissing(constructorParameterAnnotations[0].value()[0]);
}
static void assertArrayEquals(Object[] actual, Object[] expected) {
if (!Arrays.equals(actual, expected)) {
throw new AssertionError(
"expected: " + Arrays.toString(expected) + ", was: " + Arrays.toString(actual));
}
}
static void assertMissing(EnumArrayAnnotation annotation) throws Exception {
try {
annotation.value();
throw new AssertionError("expected exception");
} catch (EnumConstantNotPresentException expected) {
if (!expected.getMessage().equals("Enum.TWO")) {
throw new AssertionError(
"expected EnumConstantNotPresentException for Enum.TWO", expected);
}
}
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2016, 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.
*/
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.*;
/**
* Annotation type with a default value whose class will be missing
* when MissingTest is run.
*/
@Retention(RUNTIME)
public @interface MissingDefault {
Class<?> value() default Missing.class;
}

View file

@ -0,0 +1,150 @@
/*
* Copyright (c) 2005, 2025, 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 6322301 5041778
* @summary Verify when missing annotation classes cause exceptions
* @compile MissingTest.java A.java B.java C.java D.java Marker.java Missing.java MissingWrapper.java MissingDefault.java
* @clean Missing
* @run main MissingTest
*/
import java.lang.reflect.*;
import java.lang.annotation.*;
/**
* This test verifies that a missing annotation class leads to the
* expected exceptional behavior; a missing directly applied
* annotation is currently ignored but a missing annotation value
* inside another annotation throws an exception.
*
* To be run as intended, the annotation type Missing should *not* be
* on the classpath when the test is run; with jtreg, it is deleted by
* the @clean directive.
*/
public class MissingTest {
/**
* For the annotated element argument, get all its annotations and
* see whether or not an exception is throw upon reading the
* annotations. Additionally, verify at least one annotation is
* present.
*/
private static void testAnnotation(AnnotatedElement element,
boolean exceptionExpected) {
java.lang.annotation.Annotation[] annotations;
try {
annotations = element.getAnnotations();
if (exceptionExpected) {
System.err.println("Error: Did not get an exception reading annotations on "
+ element);
System.err.println("Annotations found: "
+ java.util.Arrays.toString(annotations));
throw new RuntimeException();
}
if (annotations.length == 0) {
System.err.println("Error: no annotations found on " + element);
throw new RuntimeException();
}
} catch (Throwable t) {
if (!exceptionExpected) {
System.err.println("Error: Got an unexpected exception reading annotations on "
+ element);
throw new RuntimeException(t);
}
}
}
/**
* For the annotated element argument, get all its annotations and
* see whether or not an exception is throw upon reading the
* annotations. Additionally, verify at least one annotation is
* present.
*/
private static void testParameterAnnotation(Method m,
boolean exceptionExpected) {
java.lang.annotation.Annotation[][] annotationsArray;
try {
annotationsArray = m.getParameterAnnotations();
if (exceptionExpected) {
System.err.println("Error: Did not get an exception reading annotations on method"
+ m);
System.err.println("Annotations found: "
+ java.util.Arrays.toString(annotationsArray));
throw new RuntimeException();
}
if (annotationsArray.length == 0 ) {
System.err.println("Error: no parameters for " + m);
throw new RuntimeException();
} else {
java.lang.annotation.Annotation[] annotations = annotationsArray[0];
if (annotations.length == 0) {
System.err.println("Error: no annotations on " + m);
throw new RuntimeException();
}
}
} catch (Throwable t) {
if (!exceptionExpected) {
System.err.println("Error: Got an unexpected exception reading annotations on "
+ m);
throw new RuntimeException(t);
}
}
}
private static void testMethodGetDefaultValue(Class<?> clazz) throws Exception{
Method m = clazz.getMethod("value", (Class<?>[])null);
try {
System.out.println(m.getDefaultValue());
throw new RuntimeException("Expected exception not thrown");
} catch (TypeNotPresentException tnpe) {
; // Expected
} catch (AnnotationFormatError afe) {
throw new RuntimeException(afe);
}
}
public static void main(String... args) throws Exception {
// Class A has a directly applied annotation whose class is
// missing.
testAnnotation(A.class, false);
// Class B has a directly applied annotation whose value
// includes to an annotation class that is missing.
testAnnotation(B.class, true);
// Class C has a directly applied parameter annotation whose
// class is missing.
testParameterAnnotation(C.class.getDeclaredMethod("method1", Object.class),
false);
// Class D has a directly applied parameter annotation whose value
// includes to an annotation class that is missing.
testParameterAnnotation(D.class.getDeclaredMethod("method1", Object.class),
true);
// The MissingDefault annotation type has a default value of the Missing class.
testMethodGetDefaultValue(MissingDefault.class);
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2005, 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.
*/
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.*;
/**
* Annotation wrapper around an annotation whose class will be missing
* when MissingTest is run.
*/
@Retention(RUNTIME)
public @interface MissingWrapper {
Missing value();
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2004, 2011, 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.
*/
public class PackageMain {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("foo.bar.Baz");
System.out.println("c=" + c);
System.out.println("cl=" + c.getClassLoader());
Package p = c.getPackage();
System.out.println("p=" + p);
Deprecated d = p.getAnnotation(Deprecated.class);
if (d == null) throw new Error();
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2008, 2024, 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 6761678 8162817
* @summary Check properties of Annotations returned from getParameterAnnotations
* @run main ParameterAnnotations
* @author Martin Buchholz
*/
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@interface Named {
String value();
}
public class ParameterAnnotations {
public void nop(@Named("foo") Object foo,
@Named("bar") Object bar) {
}
void test(String[] args) throws Throwable {
for (Method m : thisClass.getMethods()) {
if (m.getName().equals("nop")) {
Annotation[][] ann = m.getParameterAnnotations();
equal(ann.length, 2);
Annotation foo = ann[0][0];
Annotation bar = ann[1][0];
equal(foo.toString(), "@Named(\"foo\")");
equal(bar.toString(), "@Named(\"bar\")");
check(foo.equals(foo));
check(! foo.equals(bar));
}
}
}
//--------------------- Infrastructure ---------------------------
volatile int passed = 0, failed = 0;
void pass() {passed++;}
void fail() {failed++; Thread.dumpStack();}
void fail(String msg) {System.err.println(msg); fail();}
void unexpected(Throwable t) {failed++; t.printStackTrace();}
void check(boolean cond) {if (cond) pass(); else fail();}
void equal(Object x, Object y) {
if (x == null ? y == null : x.equals(y)) pass();
else fail(x + " not equal to " + y);}
static Class<?> thisClass = new Object(){}.getClass().getEnclosingClass();
public static void main(String[] args) throws Throwable {
try {thisClass.getMethod("instanceMain",String[].class)
.invoke(thisClass.newInstance(), (Object) args);}
catch (Throwable e) {throw e.getCause();}}
public void instanceMain(String[] args) throws Throwable {
try {test(args);} catch (Throwable t) {unexpected(t);}
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new AssertionError("Some tests failed");}
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2004, 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 5037685
* @summary Under certain circumstances, recursive annotations disappeared
* @author Josh Bloch
*/
import java.lang.annotation.*;
import static java.lang.annotation.RetentionPolicy.*;
@Rat public class RecursiveAnnotation {
public static void main(String[] args) {
if (!RecursiveAnnotation.class.isAnnotationPresent(Rat.class))
throw new RuntimeException("RecursiveAnnotation");
if (!Rat.class.isAnnotationPresent(Rat.class))
throw new RuntimeException("Rat");
}
}
@Retention(RUNTIME) @Rat @interface Rat { }

View file

@ -0,0 +1,252 @@
/*
* Copyright (c) 2017, 2022, 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 8074977
* @summary Test consistency of annotations on constructor parameters
* @compile TestConstructorParameterAnnotations.java
* @run main TestConstructorParameterAnnotations
* @compile -parameters TestConstructorParameterAnnotations.java
* @run main TestConstructorParameterAnnotations
*/
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
/*
* Some constructor parameters are <em>mandated</em>; that is, they
* are not explicitly present in the source code, but required to be
* present by the Java Language Specification. In other cases, some
* constructor parameters are not present in the source, but are
* synthesized by the compiler as an implementation artifact. There is
* not a reliable mechanism to consistently determine whether or not
* a parameter is implicit or not.
*
* (Using the "-parameters" option to javac does emit the information
* needed to make a reliably determination, but the information is not
* present by default.)
*
* The lack of such a mechanism causes complications reading parameter
* annotations in some cases since annotations for parameters are
* written out for the parameters in the source code, but when reading
* annotations at runtime all the parameters, including implicit ones,
* are present.
*/
public class TestConstructorParameterAnnotations {
public static void main(String... args) {
int errors = 0;
Class<?>[] classes = {NestedClass0.class,
NestedClass1.class,
NestedClass2.class,
NestedClass3.class,
NestedClass4.class,
StaticNestedClass0.class,
StaticNestedClass1.class,
StaticNestedClass2.class,
StaticNestedClass3.class,
StaticNestedClass4.class};
for (Class<?> clazz : classes) {
for (Constructor<?> ctor : clazz.getConstructors()) {
System.out.println(ctor);
errors += checkGetParameterAnnotations(clazz, ctor);
errors += checkGetParametersGetAnnotation(clazz, ctor);
}
}
if (errors > 0)
throw new RuntimeException(errors + " errors.");
return;
}
private static int checkGetParameterAnnotations(Class<?> clazz,
Constructor<?> ctor) {
String annotationString =
Arrays.deepToString(ctor.getParameterAnnotations());
String expectedString =
clazz.getAnnotation(ExpectedGetParameterAnnotations.class).value();
if (!Objects.equals(annotationString, expectedString)) {
System.err.println("Annotation mismatch on " + ctor +
"\n\tExpected:" + expectedString +
"\n\tActual: " + annotationString);
return 1;
}
return 0;
}
private static int checkGetParametersGetAnnotation(Class<?> clazz,
Constructor<?> ctor) {
int errors = 0;
int i = 0;
ExpectedParameterAnnotations epa =
clazz.getAnnotation(ExpectedParameterAnnotations.class);
for (Parameter param : ctor.getParameters() ) {
String annotationString =
Objects.toString(param.getAnnotation(MarkerAnnotation.class));
String expectedString = epa.value()[i];
if (!Objects.equals(annotationString, expectedString)) {
System.err.println("Annotation mismatch on " + ctor +
" on param " + param +
"\n\tExpected:" + expectedString +
"\n\tActual: " + annotationString);
errors++;
}
i++;
}
return errors;
}
@ExpectedGetParameterAnnotations("[[]]")
@ExpectedParameterAnnotations({"null"})
public class NestedClass0 {
public NestedClass0() {}
}
@ExpectedGetParameterAnnotations(
"[[], " +
"[@TestConstructorParameterAnnotations.MarkerAnnotation(1)]]")
@ExpectedParameterAnnotations({
"null",
"@TestConstructorParameterAnnotations.MarkerAnnotation(1)"})
public class NestedClass1 {
public NestedClass1(@MarkerAnnotation(1) int parameter) {}
}
@ExpectedGetParameterAnnotations(
"[[], " +
"[@TestConstructorParameterAnnotations.MarkerAnnotation(2)], " +
"[]]")
@ExpectedParameterAnnotations({
"null",
"@TestConstructorParameterAnnotations.MarkerAnnotation(2)",
"null"})
public class NestedClass2 {
public NestedClass2(@MarkerAnnotation(2) int parameter1,
int parameter2) {}
}
@ExpectedGetParameterAnnotations(
"[[], " +
"[@TestConstructorParameterAnnotations.MarkerAnnotation(3)], " +
"[]]")
@ExpectedParameterAnnotations({
"null",
"@TestConstructorParameterAnnotations.MarkerAnnotation(3)",
"null"})
public class NestedClass3 {
public <P> NestedClass3(@MarkerAnnotation(3) P parameter1,
int parameter2) {}
}
@ExpectedGetParameterAnnotations(
"[[], " +
"[@TestConstructorParameterAnnotations.MarkerAnnotation(4)], " +
"[]]")
@ExpectedParameterAnnotations({
"null",
"@TestConstructorParameterAnnotations.MarkerAnnotation(4)",
"null"})
public class NestedClass4 {
public <P, Q> NestedClass4(@MarkerAnnotation(4) P parameter1,
Q parameter2) {}
}
@ExpectedGetParameterAnnotations("[]")
@ExpectedParameterAnnotations({"null"})
public static class StaticNestedClass0 {
public StaticNestedClass0() {}
}
@ExpectedGetParameterAnnotations(
"[[@TestConstructorParameterAnnotations.MarkerAnnotation(1)]]")
@ExpectedParameterAnnotations({
"@TestConstructorParameterAnnotations.MarkerAnnotation(1)"})
public static class StaticNestedClass1 {
public StaticNestedClass1(@MarkerAnnotation(1) int parameter) {}
}
@ExpectedGetParameterAnnotations(
"[[@TestConstructorParameterAnnotations.MarkerAnnotation(2)], " +
"[]]")
@ExpectedParameterAnnotations({
"@TestConstructorParameterAnnotations.MarkerAnnotation(2)",
"null"})
public static class StaticNestedClass2 {
public StaticNestedClass2(@MarkerAnnotation(2) int parameter1,
int parameter2) {}
}
@ExpectedGetParameterAnnotations(
"[[@TestConstructorParameterAnnotations.MarkerAnnotation(3)], " +
"[]]")
@ExpectedParameterAnnotations({
"@TestConstructorParameterAnnotations.MarkerAnnotation(3)",
"null"})
public static class StaticNestedClass3 {
public <P> StaticNestedClass3(@MarkerAnnotation(3) P parameter1,
int parameter2) {}
}
@ExpectedGetParameterAnnotations(
"[[@TestConstructorParameterAnnotations.MarkerAnnotation(4)], " +
"[]]")
@ExpectedParameterAnnotations({
"@TestConstructorParameterAnnotations.MarkerAnnotation(4)",
"null"})
public static class StaticNestedClass4 {
public <P, Q> StaticNestedClass4(@MarkerAnnotation(4) P parameter1,
Q parameter2) {}
}
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@interface MarkerAnnotation {
int value();
}
/**
* String form of expected value of calling
* getParameterAnnotations on a constructor.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface ExpectedGetParameterAnnotations {
String value();
}
/**
* String form of expected value of calling
* getAnnotation(MarkerAnnotation.class) on each element of the
* result of getParameters() on a constructor.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface ExpectedParameterAnnotations {
String[] value();
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2011, 2025, 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 7021922
* @summary Test null handling of IncompleteAnnotationException constructor
*/
import java.lang.annotation.*;
public class TestIncompleteAnnotationExceptionNPE {
public static void main(String... args) {
int errors = 0;
Class<? extends Annotation> annotationType = Annotation.class;
String elementName = "name";
try {
Object o = new IncompleteAnnotationException(null, null);
errors++;
} catch(NullPointerException npe) {
; // Expected
}
try {
Object o = new IncompleteAnnotationException(annotationType, null);
errors++;
} catch(NullPointerException npe) {
; // Expected
}
try {
Object o = new IncompleteAnnotationException(null, elementName);
errors++;
} catch(NullPointerException npe) {
; // Expected
}
if (errors != 0)
throw new RuntimeException("Encountered " + errors +
" error(s) during construction.");
}
}

View file

@ -0,0 +1,659 @@
/*
* Copyright (c) 2013, 2015, 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 8004698 8007073 8022343 8054304 8057804 8058595
* @summary Unit test for type annotations
*/
import java.util.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.io.Serializable;
public class TypeAnnotationReflection {
public static void main(String[] args) throws Exception {
testSuper();
testInterfaces();
testReturnType();
testNested();
testArray();
testRunException(TestClassException.class.getDeclaredMethod("foo", (Class<?>[])null));
testRunException(Outer2.TestClassException2.class.getDeclaredConstructor(Outer2.class));
testClassTypeVarBounds();
testMethodTypeVarBounds();
testFields();
testClassTypeVar();
testMethodTypeVar();
testParameterizedType();
testNestedParameterizedType();
testWildcardType();
testParameterTypes();
testParameterType();
}
private static void check(boolean b) {
if (!b)
throw new RuntimeException();
}
private static void testSuper() throws Exception {
check(Object.class.getAnnotatedSuperclass() == null);
check(Class.class.getAnnotatedSuperclass().getAnnotations().length == 0);
AnnotatedType a;
a = TestClassArray.class.getAnnotatedSuperclass();
Annotation[] annos = a.getAnnotations();
check(annos.length == 2);
check(annos[0].annotationType().equals(TypeAnno.class));
check(annos[1].annotationType().equals(TypeAnno2.class));
check(((TypeAnno)annos[0]).value().equals("extends"));
check(((TypeAnno2)annos[1]).value().equals("extends2"));
}
private static void testInterfaces() throws Exception {
AnnotatedType[] as;
as = TestClassArray.class.getAnnotatedInterfaces();
check(as.length == 3);
check(as[1].getAnnotations().length == 0);
Annotation[] annos;
annos = as[0].getAnnotations();
check(annos.length == 2);
check(annos[0].annotationType().equals(TypeAnno.class));
check(annos[1].annotationType().equals(TypeAnno2.class));
check(((TypeAnno)annos[0]).value().equals("implements serializable"));
check(((TypeAnno2)annos[1]).value().equals("implements2 serializable"));
annos = as[2].getAnnotations();
check(annos.length == 2);
check(annos[0].annotationType().equals(TypeAnno.class));
check(annos[1].annotationType().equals(TypeAnno2.class));
check(((TypeAnno)annos[0]).value().equals("implements cloneable"));
check(((TypeAnno2)annos[1]).value().equals("implements2 cloneable"));
}
private static void testReturnType() throws Exception {
Method m = TestClassArray.class.getDeclaredMethod("foo", (Class<?>[])null);
Annotation[] annos = m.getAnnotatedReturnType().getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("return1"));
}
private static void testNested() throws Exception {
Method m = TestClassNested.class.getDeclaredMethod("foo", (Class<?>[])null);
Annotation[] annos = m.getAnnotatedReturnType().getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("array"));
AnnotatedType t = m.getAnnotatedReturnType();
t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType();
annos = t.getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("Inner"));
}
private static void testArray() throws Exception {
Method m = TestClassArray.class.getDeclaredMethod("foo", (Class<?>[])null);
AnnotatedArrayType t = (AnnotatedArrayType) m.getAnnotatedReturnType();
Annotation[] annos = t.getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("return1"));
t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType();
annos = t.getAnnotations();
check(annos.length == 0);
t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType();
annos = t.getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("return3"));
AnnotatedType tt = t.getAnnotatedGenericComponentType();
check(!(tt instanceof AnnotatedArrayType));
annos = tt.getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("return4"));
}
private static void testRunException(Executable e) throws Exception {
AnnotatedType[] ts = e.getAnnotatedExceptionTypes();
check(ts.length == 3);
AnnotatedType t;
Annotation[] annos;
t = ts[0];
annos = t.getAnnotations();
check(annos.length == 2);
check(annos[0].annotationType().equals(TypeAnno.class));
check(annos[1].annotationType().equals(TypeAnno2.class));
check(((TypeAnno)annos[0]).value().equals("RE"));
check(((TypeAnno2)annos[1]).value().equals("RE2"));
t = ts[1];
annos = t.getAnnotations();
check(annos.length == 0);
t = ts[2];
annos = t.getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("AIOOBE"));
}
private static void testClassTypeVarBounds() throws Exception {
Method m = TestClassTypeVarAndField.class.getDeclaredMethod("foo", (Class<?>[])null);
AnnotatedType ret = m.getAnnotatedReturnType();
Annotation[] annos = ret.getAnnotations();
check(annos.length == 2);
AnnotatedType[] annotatedBounds = ((AnnotatedTypeVariable)ret).getAnnotatedBounds();
check(annotatedBounds.length == 2);
annos = annotatedBounds[0].getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("Object1"));
annos = annotatedBounds[1].getAnnotations();
check(annos.length == 2);
check(annos[0].annotationType().equals(TypeAnno.class));
check(annos[1].annotationType().equals(TypeAnno2.class));
check(((TypeAnno)annos[0]).value().equals("Runnable1"));
check(((TypeAnno2)annos[1]).value().equals("Runnable2"));
}
private static void testMethodTypeVarBounds() throws Exception {
Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class<?>[])null);
AnnotatedType ret2 = m2.getAnnotatedReturnType();
AnnotatedType[] annotatedBounds2 = ((AnnotatedTypeVariable)ret2).getAnnotatedBounds();
check(annotatedBounds2.length == 1);
Annotation[] annos = annotatedBounds2[0].getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("M Runnable"));
// Check that AnnotatedTypeVariable.getAnnotatedBounds() returns jlO for a naked
// type variable (i.e no bounds, no annotations)
Method m4 = TestClassTypeVarAndField.class.getDeclaredMethod("foo4", (Class<?>[])null);
AnnotatedType ret4 = m4.getAnnotatedReturnType();
AnnotatedType[] annotatedBounds4 = ((AnnotatedTypeVariable)ret4).getAnnotatedBounds();
check(annotatedBounds4.length == 1);
annos = annotatedBounds4[0].getAnnotations();
check(annos.length == 0);
check(annotatedBounds4[0].getType().equals(Object.class));
}
private static void testFields() throws Exception {
Field f1 = TestClassTypeVarAndField.class.getDeclaredField("field1");
AnnotatedType at;
Annotation[] annos;
at = f1.getAnnotatedType();
annos = at.getAnnotations();
check(annos.length == 2);
check(annos[0].annotationType().equals(TypeAnno.class));
check(annos[1].annotationType().equals(TypeAnno2.class));
check(((TypeAnno)annos[0]).value().equals("T1 field"));
check(((TypeAnno2)annos[1]).value().equals("T2 field"));
Field f2 = TestClassTypeVarAndField.class.getDeclaredField("field2");
at = f2.getAnnotatedType();
annos = at.getAnnotations();
check(annos.length == 0);
Field f3 = TestClassTypeVarAndField.class.getDeclaredField("field3");
at = f3.getAnnotatedType();
annos = at.getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("Object field"));
}
private static void testClassTypeVar() throws Exception {
TypeVariable[] typeVars = TestClassTypeVarAndField.class.getTypeParameters();
Annotation[] annos;
check(typeVars.length == 3);
// First TypeVar
AnnotatedType[] annotatedBounds = typeVars[0].getAnnotatedBounds();
check(annotatedBounds.length == 2);
annos = annotatedBounds[0].getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("Object1"));
annos = annotatedBounds[1].getAnnotations();
check(annos.length == 2);
check(annos[0].annotationType().equals(TypeAnno.class));
check(annos[1].annotationType().equals(TypeAnno2.class));
check(((TypeAnno)annos[0]).value().equals("Runnable1"));
check(((TypeAnno2)annos[1]).value().equals("Runnable2"));
// second TypeVar regular anno
Annotation[] regularAnnos = typeVars[1].getAnnotations();
check(regularAnnos.length == 1);
check(typeVars[1].getAnnotation(TypeAnno.class).value().equals("EE"));
// second TypeVar
annotatedBounds = typeVars[1].getAnnotatedBounds();
check(annotatedBounds.length == 1);
annos = annotatedBounds[0].getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno2.class));
check(((TypeAnno2)annos[0]).value().equals("EEBound"));
// third Typevar V declared without explicit bounds should see jlO as its bound.
annotatedBounds = typeVars[2].getAnnotatedBounds();
check(annotatedBounds.length == 1);
annos = annotatedBounds[0].getAnnotations();
check(annos.length == 0);
check(annotatedBounds[0].getType().equals(Object.class));
}
private static void testMethodTypeVar() throws Exception {
Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class<?>[])null);
TypeVariable[] t = m2.getTypeParameters();
check(t.length == 1);
Annotation[] annos = t[0].getAnnotations();
check(annos.length == 0);
AnnotatedType[] annotatedBounds2 = t[0].getAnnotatedBounds();
check(annotatedBounds2.length == 1);
annos = annotatedBounds2[0].getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("M Runnable"));
// Second method
m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo3", (Class<?>[])null);
t = m2.getTypeParameters();
check(t.length == 2);
annos = t[0].getAnnotations();
check(annos.length == 1);
check(annos[0].annotationType().equals(TypeAnno.class));
check(((TypeAnno)annos[0]).value().equals("K"));
annotatedBounds2 = t[0].getAnnotatedBounds();
check(annotatedBounds2.length == 1);
annos = annotatedBounds2[0].getAnnotations();
check(annos.length == 0);
// for the naked type variable L of foo3, we should see jlO as its bound.
annotatedBounds2 = t[1].getAnnotatedBounds();
check(annotatedBounds2.length == 1);
check(annotatedBounds2[0].getType().equals(Object.class));
annos = annotatedBounds2[0].getAnnotations();
check(annos.length == 0);
}
private static void testParameterizedType() {
// Base
AnnotatedType[] as;
as = TestParameterizedType.class.getAnnotatedInterfaces();
check(as.length == 1);
check(as[0].getAnnotations().length == 1);
check(as[0].getAnnotation(TypeAnno.class).value().equals("M"));
Annotation[] annos;
as = ((AnnotatedParameterizedType)as[0]).getAnnotatedActualTypeArguments();
check(as.length == 2);
annos = as[0].getAnnotations();
check(annos.length == 1);
check(as[0].getAnnotation(TypeAnno.class).value().equals("S"));
check(as[0].getAnnotation(TypeAnno2.class) == null);
annos = as[1].getAnnotations();
check(annos.length == 2);
check(((TypeAnno)annos[0]).value().equals("I"));
check(as[1].getAnnotation(TypeAnno2.class).value().equals("I2"));
}
private static void testNestedParameterizedType() throws Exception {
Method m = TestParameterizedType.class.getDeclaredMethod("foo2", (Class<?>[])null);
AnnotatedType ret = m.getAnnotatedReturnType();
Annotation[] annos;
annos = ret.getAnnotations();
check(annos.length == 1);
check(((TypeAnno)annos[0]).value().equals("I"));
AnnotatedType[] args = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments();
check(args.length == 1);
annos = args[0].getAnnotations();
check(annos.length == 2);
check(((TypeAnno)annos[0]).value().equals("I1"));
check(args[0].getAnnotation(TypeAnno2.class).value().equals("I2"));
// check type args
Field f = TestParameterizedType.class.getDeclaredField("theField");
AnnotatedParameterizedType fType = (AnnotatedParameterizedType)f.getAnnotatedType();
args = fType.getAnnotatedActualTypeArguments();
check(args.length == 1);
annos = args[0].getAnnotations();
check(annos.length == 1);
check(((TypeAnno2)annos[0]).value().equals("Map Arg"));
check(args[0].getAnnotation(TypeAnno2.class).value().equals("Map Arg"));
// check outer type type args
fType = (AnnotatedParameterizedType)fType.getAnnotatedOwnerType();
args = fType.getAnnotatedActualTypeArguments();
check(args.length == 1);
annos = args[0].getAnnotations();
check(annos.length == 1);
check(((TypeAnno2)annos[0]).value().equals("String Arg"));
check(args[0].getAnnotation(TypeAnno2.class).value().equals("String Arg"));
// check outer type normal type annotations
annos = fType.getAnnotations();
check(annos.length == 1);
check(((TypeAnno)annos[0]).value().equals("FieldOuter"));
check(fType.getAnnotation(TypeAnno.class).value().equals("FieldOuter"));
}
private static void testWildcardType() throws Exception {
Method m = TestWildcardType.class.getDeclaredMethod("foo", (Class<?>[])null);
AnnotatedType ret = m.getAnnotatedReturnType();
AnnotatedType[] t;
t = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments();
check(t.length == 1);
ret = t[0];
Field f = TestWildcardType.class.getDeclaredField("f1");
AnnotatedWildcardType w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
.getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
t = w.getAnnotatedLowerBounds();
check(t.length == 0);
t = w.getAnnotatedUpperBounds();
check(t.length == 1);
Annotation[] annos;
annos = t[0].getAnnotations();
check(annos.length == 1);
check(((TypeAnno)annos[0]).value().equals("2"));
f = TestWildcardType.class.getDeclaredField("f2");
w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
.getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
t = w.getAnnotatedUpperBounds();
check(t.length == 1);
check(t[0].getType().equals(Object.class));
annos = t[0].getAnnotations();
check(annos.length == 0);
t = w.getAnnotatedLowerBounds();
check(t.length == 1);
// for an unbounded wildcard, we should see jlO as its upperbound and null type as its lower bound.
f = TestWildcardType.class.getDeclaredField("f3");
w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
.getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
t = w.getAnnotatedUpperBounds();
check(t.length == 1);
check(t[0].getType().equals(Object.class));
annos = t[0].getAnnotations();
check(annos.length == 0);
t = w.getAnnotatedLowerBounds();
check(t.length == 0);
}
private static void testParameterTypes() throws Exception {
// NO PARAMS
Method m = Params.class.getDeclaredMethod("noParams", (Class<?>[])null);
AnnotatedType[] t = m.getAnnotatedParameterTypes();
check(t.length == 0);
// ONLY ANNOTATED PARAM TYPES
Class[] argsArr = {String.class, String.class, String.class};
m = Params.class.getDeclaredMethod("onlyAnnotated", (Class<?>[])argsArr);
t = m.getAnnotatedParameterTypes();
check(t.length == 3);
check(t[0].getAnnotations().length == 1);
check(t[0].getAnnotation(TypeAnno.class) != null);
check(t[0].getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
check(t[1].getAnnotations().length == 1);
check(t[1].getAnnotation(TypeAnno.class) != null);
check(t[1].getAnnotationsByType(TypeAnno.class)[0].value().equals("2"));
check(t[2].getAnnotations().length == 2);
check(t[2].getAnnotations()[0].annotationType().equals(TypeAnno.class));
check(t[2].getAnnotation(TypeAnno.class) != null);
check(t[2].getAnnotation(TypeAnno2.class) != null);
check(t[2].getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
check(t[2].getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
// MIXED ANNOTATED PARAM TYPES
m = Params.class.getDeclaredMethod("mixed", (Class<?>[])argsArr);
t = m.getAnnotatedParameterTypes();
check(t.length == 3);
check(t[0].getAnnotations().length == 1);
check(t[0].getAnnotation(TypeAnno.class) != null);
check(t[0].getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
check(t[1].getAnnotations().length == 0);
check(t[1].getAnnotation(TypeAnno.class) == null);
check(t[1].getAnnotation(TypeAnno2.class) == null);
check(t[2].getAnnotations().length == 2);
check(t[2].getAnnotations()[0].annotationType().equals(TypeAnno.class));
check(t[2].getAnnotation(TypeAnno.class) != null);
check(t[2].getAnnotation(TypeAnno2.class) != null);
check(t[2].getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
check(t[2].getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
// NO ANNOTATED PARAM TYPES
m = Params.class.getDeclaredMethod("unAnnotated", (Class<?>[])argsArr);
t = m.getAnnotatedParameterTypes();
check(t.length == 3);
check(t[0].getAnnotations().length == 0);
check(t[0].getAnnotation(TypeAnno.class) == null);
check(t[0].getAnnotation(TypeAnno2.class) == null);
check(t[1].getAnnotations().length == 0);
check(t[1].getAnnotation(TypeAnno.class) == null);
check(t[1].getAnnotation(TypeAnno2.class) == null);
check(t[2].getAnnotations().length == 0);
check(t[2].getAnnotation(TypeAnno.class) == null);
check(t[2].getAnnotation(TypeAnno2.class) == null);
}
private static void testParameterType() throws Exception {
// NO PARAMS
Method m = Params.class.getDeclaredMethod("noParams", (Class<?>[])null);
Parameter[] p = m.getParameters();
check(p.length == 0);
// ONLY ANNOTATED PARAM TYPES
Class[] argsArr = {String.class, String.class, String.class};
m = Params.class.getDeclaredMethod("onlyAnnotated", (Class<?>[])argsArr);
p = m.getParameters();
check(p.length == 3);
AnnotatedType t0 = p[0].getAnnotatedType();
AnnotatedType t1 = p[1].getAnnotatedType();
AnnotatedType t2 = p[2].getAnnotatedType();
check(t0.getAnnotations().length == 1);
check(t0.getAnnotation(TypeAnno.class) != null);
check(t0.getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
check(t1.getAnnotations().length == 1);
check(t1.getAnnotation(TypeAnno.class) != null);
check(t1.getAnnotationsByType(TypeAnno.class)[0].value().equals("2"));
check(t2.getAnnotations().length == 2);
check(t2.getAnnotations()[0].annotationType().equals(TypeAnno.class));
check(t2.getAnnotation(TypeAnno.class) != null);
check(t2.getAnnotation(TypeAnno2.class) != null);
check(t2.getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
check(t2.getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
// MIXED ANNOTATED PARAM TYPES
m = Params.class.getDeclaredMethod("mixed", (Class<?>[])argsArr);
p = m.getParameters();
check(p.length == 3);
t0 = p[0].getAnnotatedType();
t1 = p[1].getAnnotatedType();
t2 = p[2].getAnnotatedType();
check(t0.getAnnotations().length == 1);
check(t0.getAnnotation(TypeAnno.class) != null);
check(t0.getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
check(t1.getAnnotations().length == 0);
check(t1.getAnnotation(TypeAnno.class) == null);
check(t1.getAnnotation(TypeAnno2.class) == null);
check(t2.getAnnotations().length == 2);
check(t2.getAnnotations()[0].annotationType().equals(TypeAnno.class));
check(t2.getAnnotation(TypeAnno.class) != null);
check(t2.getAnnotation(TypeAnno2.class) != null);
check(t2.getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
check(t2.getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
// NO ANNOTATED PARAM TYPES
m = Params.class.getDeclaredMethod("unAnnotated", (Class<?>[])argsArr);
p = m.getParameters();
check(p.length == 3);
t0 = p[0].getAnnotatedType();
t1 = p[1].getAnnotatedType();
t2 = p[2].getAnnotatedType();
check(t0.getAnnotations().length == 0);
check(t0.getAnnotation(TypeAnno.class) == null);
check(t0.getAnnotation(TypeAnno2.class) == null);
check(t1.getAnnotations().length == 0);
check(t1.getAnnotation(TypeAnno.class) == null);
check(t1.getAnnotation(TypeAnno2.class) == null);
check(t2.getAnnotations().length == 0);
check(t2.getAnnotation(TypeAnno.class) == null);
check(t2.getAnnotation(TypeAnno2.class) == null);
}
}
class Params {
public void noParams() {}
public void onlyAnnotated(@TypeAnno("1") String s1, @TypeAnno("2") String s2, @TypeAnno("3a") @TypeAnno2("3b") String s3) {}
public void mixed(@TypeAnno("1") String s1, String s2, @TypeAnno("3a") @TypeAnno2("3b") String s3) {}
public void unAnnotated(String s1, String s2, String s3) {}
}
abstract class TestWildcardType {
public <T> List<? super T> foo() { return null;}
public Class<@TypeAnno("1") ? extends @TypeAnno("2") Annotation> f1;
public Class<@TypeAnno("3") ? super @TypeAnno("4") Annotation> f2;
public Class<@TypeAnno("5") ?> f3;
}
abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> {
public ParameterizedOuter<String>.ParameterizedInner<Integer> foo() {return null;}
public @TypeAnno("O") ParameterizedOuter<@TypeAnno("S1") @TypeAnno2("S2") String>.
@TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() {
return null;
}
public @TypeAnno("FieldOuter") ParameterizedOuter<@TypeAnno2("String Arg") String>.
@TypeAnno("FieldInner")ParameterizedInner<@TypeAnno2("Map Arg")Map> theField;
}
class ParameterizedOuter <T> {
class ParameterizedInner <U> {}
}
abstract class TestClassArray extends @TypeAnno("extends") @TypeAnno2("extends2") Object
implements @TypeAnno("implements serializable") @TypeAnno2("implements2 serializable") Serializable,
Readable,
@TypeAnno("implements cloneable") @TypeAnno2("implements2 cloneable") Cloneable {
public @TypeAnno("return4") Object @TypeAnno("return1") [][] @TypeAnno("return3")[] foo() { return null; }
}
abstract class TestClassNested {
public @TypeAnno("Outer") Outer.@TypeAnno("Inner")Inner @TypeAnno("array")[] foo() { return null; }
}
class Outer {
class Inner {
}
}
abstract class TestClassException {
public Object foo() throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException,
NullPointerException,
@TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException {
return null;
}
}
class Outer2 {
abstract class TestClassException2 {
public TestClassException2() throws
@TypeAnno("RE") @TypeAnno2("RE2") RuntimeException,
NullPointerException,
@TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException {}
}
}
abstract class TestClassTypeVarAndField <T extends @TypeAnno("Object1") Object
& @TypeAnno("Runnable1") @TypeAnno2("Runnable2") Runnable,
@TypeAnno("EE")EE extends @TypeAnno2("EEBound") Runnable, V > {
@TypeAnno("T1 field") @TypeAnno2("T2 field") T field1;
T field2;
@TypeAnno("Object field") Object field3;
public @TypeAnno("t1") @TypeAnno2("t2") T foo(){ return null; }
public <M extends @TypeAnno("M Runnable") Runnable> M foo2() {return null;}
public <@TypeAnno("K") K extends Cloneable, L> K foo3() {return null;}
public <L> L foo4() {return null;}
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno {
String value();
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno2 {
String value();
}

View file

@ -0,0 +1,120 @@
/*
* 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 8004698 8007278
* @summary Unit test for annotations on TypeVariables
*/
import java.util.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.io.Serializable;
public class TypeParamAnnotation {
public static void main(String[] args) throws Exception {
testOnClass();
testOnMethod();
testGetAnno();
testGetAnnos();
}
private static void check(boolean b) {
if (!b)
throw new RuntimeException();
}
private static void testOnClass() {
TypeVariable<?>[] ts = TypeParam.class.getTypeParameters();
check(ts.length == 3);
Annotation[] as;
as = ts[0].getAnnotations();
check(as.length == 2);
check(((ParamAnno)as[0]).value().equals("t"));
check(((ParamAnno2)as[1]).value() == 1);
as = ts[1].getAnnotations();
check(as.length == 0);
as = ts[2].getAnnotations();
check(as.length == 2);
check(((ParamAnno)as[0]).value().equals("v"));
check(((ParamAnno2)as[1]).value() == 2);
}
private static void testOnMethod() throws Exception {
TypeVariable<?>[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters();
check(ts.length == 3);
Annotation[] as;
as = ts[0].getAnnotations();
check(as.length == 2);
check(((ParamAnno)as[0]).value().equals("x"));
check(((ParamAnno2)as[1]).value() == 3);
as = ts[1].getAnnotations();
check(as.length == 0);
as = ts[2].getAnnotations();
check(as.length == 2);
check(((ParamAnno)as[0]).value().equals("z"));
check(((ParamAnno2)as[1]).value() == 4);
}
private static void testGetAnno() {
TypeVariable<?>[] ts = TypeParam.class.getTypeParameters();
ParamAnno a;
a = ts[0].getAnnotation(ParamAnno.class);
check(a.value().equals("t"));
}
private static void testGetAnnos() throws Exception {
TypeVariable<?>[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters();
ParamAnno2[] as;
as = ts[0].getAnnotationsByType(ParamAnno2.class);
check(as.length == 1);
check(as[0].value() == 3);
}
}
class TypeParam <@ParamAnno("t") @ParamAnno2(1) T,
U,
@ParamAnno("v") @ParamAnno2(2) V extends Runnable> {
public <@ParamAnno("x") @ParamAnno2(3) X,
Y,
@ParamAnno("z") @ParamAnno2(4) Z extends Cloneable> void foo() {}
}
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@interface ParamAnno {
String value();
}
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@interface ParamAnno2 {
int value();
}

View file

@ -0,0 +1,129 @@
/*
* Copyright (c) 2014, 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 8038994
* @summary Test that getAnnotatedBounds().getType() match getBounds()
* @run testng TypeVariableBounds
*/
import java.io.Serializable;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.concurrent.Callable;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class TypeVariableBounds {
@Test(dataProvider = "classData")
public void testClass(Class<?> c) throws Exception {
assertNotEquals(c.getTypeParameters().length, 0);
TypeVariable[] tv = c.getTypeParameters();
for(TypeVariable t : tv)
testTv(t);
}
@Test(dataProvider = "methodData")
public void testMethod(Class<?>c) throws Exception {
Method m = c.getMethod("aMethod");
TypeVariable[] tv = m.getTypeParameters();
for(TypeVariable t : tv)
testTv(t);
}
public void testTv(TypeVariable<?> tv) {
Type[] t = tv.getBounds();
AnnotatedType[] at = tv.getAnnotatedBounds();
assertEquals(t.length, at.length, Arrays.asList(t) + " and " + Arrays.asList(at) + " should be the same length");
for (int i = 0; i < t.length; i++)
assertSame(at[i].getType(), t[i], "T: " + t[i] + ", AT: " + at[i] + ", AT.getType(): " + at[i].getType() + "\n");
}
@DataProvider
public Object[][] classData() { return CLASS_TESTS; }
@DataProvider
public Object[][] methodData() { return METHOD_TESTS; }
public static final Object[][] CLASS_TESTS = {
{ Case1.class, },
{ Case2.class, },
{ Case5.class, },
{ Case6.class, },
};
public static final Object[][] METHOD_TESTS = {
{ Case3.class, },
{ Case4.class, },
{ Case5.class, },
{ Case6.class, },
};
// Class type var
public static class Case1<C1T1, C1T2 extends AnnotatedElement, C1T3 extends AnnotatedElement & Type & Serializable> {}
public static class Case2<C2T0, @TA C2T1 extends Type, C2T2 extends @TB AnnotatedElement, C2T3 extends AnnotatedElement & @TB Type & Serializable> {}
// Method type var
public static class Case3 { public <C3T1, C3T2 extends AnnotatedElement, C3T3 extends AnnotatedElement & Type & Serializable> void aMethod() {}}
public static class Case4 { public <C4T0, @TA C4T1 extends List, C4T2 extends @TB Set, C4T3 extends Set & @TB Callable & Serializable> void aMethod() {}}
// Both
public static class Case5 <C5CT1, C5CT2 extends Runnable> {
public <C5MT1,
C5MT2 extends AnnotatedElement,
C5MT3 extends AnnotatedElement & Type & Serializable,
C5MT4 extends C5CT2>
void aMethod() {}}
public static class Case6 <@TA C6CT1, C6CT2 extends @TB Runnable> {
public <@TA C6MT1,
C6MT2 extends @TB AnnotatedElement,
C6MT3 extends @TB AnnotatedElement & @TB2 Type & Serializable,
C6MT4 extends @TB2 C6CT2>
void aMethod() {}}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_PARAMETER)
public @interface TA {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface TB {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface TB2 {}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2004, 2011, 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 4901290 5037531
* @summary Package annotations
* @author gafter
*
* @compile package-info.java PackageMain.java
* @run main PackageMain
*/
@Deprecated
package foo.bar;
class Baz {}

View file

@ -0,0 +1,120 @@
/*
* 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 8027170
* @summary getAnnotationsByType needs to take the class hierarchy into account
* when determining which annotations are associated with a given
* class.
* @run main InheritedAssociatedAnnotations
*/
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.Arrays;
public class InheritedAssociatedAnnotations {
public static void main(String[] args) {
checkAssociated(A3.class);
checkAssociated(B3.class);
checkAssociated(C3.class);
checkAssociated(D3.class);
}
private static void checkAssociated(AnnotatedElement ae) {
Ann[] actual = ae.getAnnotationsByType(Ann.class);
Ann[] expected = ae.getAnnotation(ExpectedAssociated.class).value();
if (!Arrays.equals(actual, expected)) {
throw new RuntimeException(String.format(
"Test failed for %s: Expected %s but got %s.",
ae,
Arrays.toString(expected),
Arrays.toString(actual)));
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface ExpectedAssociated {
Ann[] value();
}
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(AnnCont.class)
@interface Ann {
int value();
}
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface AnnCont {
Ann[] value();
}
@Ann(10)
class A1 {}
@Ann(20)
class A2 extends A1 {}
@ExpectedAssociated({@Ann(20)})
class A3 extends A2 {}
@Ann(10) @Ann(11)
class B1 {}
@Ann(20)
class B2 extends B1 {}
@ExpectedAssociated({@Ann(20)})
class B3 extends B2 {}
@Ann(10)
class C1 {}
@Ann(20) @Ann(21)
class C2 extends C1 {}
@ExpectedAssociated({@Ann(20), @Ann(21)})
class C3 extends C2 {}
@Ann(10) @Ann(11)
class D1 {}
@Ann(20) @Ann(21)
class D2 extends D1 {}
@ExpectedAssociated({@Ann(20), @Ann(21)})
class D3 extends D2 {}

View file

@ -0,0 +1,63 @@
/*
* 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 8019420
* @summary Repeatable non-inheritable annotation types are mishandled by Core Reflection
*/
import java.util.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
public class NonInheritableContainee {
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(InheritedAnnotationContainer.class)
@interface NonInheritedAnnotationRepeated {
String name();
}
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface InheritedAnnotationContainer {
NonInheritedAnnotationRepeated[] value();
}
@NonInheritedAnnotationRepeated(name="A")
@NonInheritedAnnotationRepeated(name="B")
class Parent {}
class Sample extends Parent {}
public static void main(String[] args) {
Annotation[] anns = Sample.class.getAnnotationsByType(
NonInheritedAnnotationRepeated.class);
if (anns.length != 0)
throw new RuntimeException("Non-@Inherited containees should not " +
"be inherited even though its container is @Inherited.");
}
}

View file

@ -0,0 +1,74 @@
/*
* 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 8004912
* @summary Unit test for order of annotations returned by get[Declared]AnnotationsByType.
*
* @run main OrderUnitTest
*/
import java.lang.annotation.*;
import java.lang.reflect.*;
public class OrderUnitTest {
public static void main(String[] args) {
testOrder(Case1.class);
testOrder(Case2.class);
}
private static void testOrder(AnnotatedElement e) {
Annotation[] decl = e.getDeclaredAnnotations();
Foo[] declByType = e.getDeclaredAnnotationsByType(Foo.class);
if (decl[0] instanceof Foo != declByType[0].isDirect() ||
decl[1] instanceof Foo != declByType[1].isDirect()) {
throw new RuntimeException("Order of directly / indirectly present " +
"annotations from getDeclaredAnnotationsByType does not " +
"match order from getDeclaredAnnotations.");
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface FooContainer {
Foo[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(FooContainer.class)
@interface Foo {
boolean isDirect();
}
@Foo(isDirect = true) @FooContainer({@Foo(isDirect = false)})
class Case1 {
}
@FooContainer({@Foo(isDirect = false)}) @Foo(isDirect = true)
class Case2 {
}

View file

@ -0,0 +1,312 @@
/*
* Copyright (c) 2012, 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 7154390 8005712 8007278 8004912
* @summary Unit test for repeated annotation reflection
*
* @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java
* @run main RepeatedUnitTest
*/
import subpackage.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
public class RepeatedUnitTest {
public static void main(String[] args) throws Exception {
// PACKAGE ANNOTATIONS
Class c = Class.forName("subpackage.NonRepeated"); // force package "subpackage" load
Package p = Package.getPackage("subpackage");
packageNonRepeated(p);
packageRepeated(p);
packageContainer(p);
// INHERITED/NON-INHERITED ON CLASS
inheritedMe1();
inheritedMe2();
inheritedMe3();
inheritedMe4();
inheritedMe5(); // ContainerOnSuperSingleOnSub
inheritedMe6(); // RepeatableOnSuperSingleOnSub
inheritedMe7(); // SingleAnnoOnSuperContainerOnSub
inheritedMe8(); // SingleOnSuperRepeatableOnSub
// CONSTRUCTOR
checkMultiplier(Me1.class.getConstructor(new Class[0]), 10);
// FIELD
checkMultiplier(Me1.class.getField("foo"), 1);
// METHOD
checkMultiplier(Me1.class.getDeclaredMethod("mee", (Class<?>[])null), 100);
// INNER CLASS
checkMultiplier(Me1.MiniMee.class, 1000);
// ENUM ELEMENT
checkMultiplier(Me1.E.class.getField("EE"), 10000);
// ENUM
checkMultiplier(Me1.E.class, 100000);
}
static void packageNonRepeated(AnnotatedElement e) {
NonRepeated nr = e.getAnnotation(NonRepeated.class);
check(nr.value() == 10);
check(1 == countAnnotation(e, NonRepeated.class));
nr = e.getAnnotationsByType(NonRepeated.class)[0];
check(nr.value() == 10);
check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class));
}
static void packageRepeated(AnnotatedElement e) {
Containee c = e.getAnnotation(Containee.class);
check(c == null);
check(2 == countAnnotation(e, Containee.class));
c = e.getAnnotationsByType(Containee.class)[0];
check(c.value() == 1);
c = e.getAnnotationsByType(Containee.class)[1];
check(c.value() == 2);
check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
}
static void packageContainer(AnnotatedElement e) {
Container cr = e.getAnnotation(Container.class);
check(null != cr);
check(1 == containsAnnotationOfType(e.getAnnotationsByType(Container.class), Container.class));
check(1 == countAnnotation(e, Container.class));
}
static void inheritedMe1() {
AnnotatedElement e = Me1.class;
check(null == e.getAnnotation(NonRepeated.class));
check(e.getAnnotation(InheritedNonRepeated.class).value() == 20);
check(0 == countAnnotation(e, Containee.class));
check(4 == countAnnotation(e, InheritedContainee.class));
check(0 == countAnnotation(e, Container.class));
check(1 == countAnnotation(e, InheritedContainer.class));
}
static void inheritedMe2() {
AnnotatedElement e = Me2.class;
check(e.getAnnotation(NonRepeated.class).value() == 100);
check(e.getAnnotation(InheritedNonRepeated.class).value() == 200);
check(4 == countAnnotation(e, Containee.class));
check(4 == countAnnotation(e, InheritedContainee.class));
check(1 == countAnnotation(e, Container.class));
check(1 == countAnnotation(e, InheritedContainer.class));
check(1 == countAnnotation(e, NonRepeated.class));
check(1 == countAnnotation(e, InheritedNonRepeated.class));
check(e.getAnnotationsByType(Containee.class)[2].value() == 300);
check(e.getAnnotationsByType(InheritedContainee.class)[2].value() == 300);
check(e.getAnnotationsByType(InheritedNonRepeated.class)[0].value() == 200);
check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 100);
}
static void inheritedMe3() {
AnnotatedElement e = Me3.class;
check(null == e.getAnnotation(NonRepeated.class));
check(0 == countAnnotation(e, Containee.class));
check(4 == countAnnotation(e, InheritedContainee.class));
check(0 == countAnnotation(e, Container.class));
check(1 == countAnnotation(e, InheritedContainer.class));
check(e.getAnnotationsByType(InheritedContainee.class)[2].value() == 350);
check(e.getAnnotationsByType(InheritedNonRepeated.class)[0].value() == 15);
}
static void inheritedMe4() {
AnnotatedElement e = Me4.class;
check(e.getAnnotation(NonRepeated.class).value() == 1000);
check(e.getAnnotation(InheritedNonRepeated.class).value() == 2000);
check(4 == countAnnotation(e, Containee.class));
check(4 == countAnnotation(e, InheritedContainee.class));
check(1 == countAnnotation(e, Container.class));
check(1 == countAnnotation(e, InheritedContainer.class));
check(1 == countAnnotation(e, NonRepeated.class));
check(1 == countAnnotation(e, InheritedNonRepeated.class));
check(e.getAnnotationsByType(Containee.class)[2].value() == 3000);
check(e.getAnnotationsByType(InheritedContainee.class)[2].value() == 3000);
check(e.getAnnotationsByType(InheritedNonRepeated.class)[0].value() == 2000);
check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 1000);
}
static void inheritedMe5() {
AnnotatedElement e = Me5.class;
check(2 == e.getAnnotations().length);
check(1 == countAnnotation(e, InheritedContainee.class));
}
static void inheritedMe6() {
AnnotatedElement e = Me6.class;
check(2 == e.getAnnotations().length);
check(1 == countAnnotation(e, InheritedContainee.class));
}
static void inheritedMe7() {
AnnotatedElement e = Me7.class;
check(2 == e.getAnnotations().length);
check(2 == countAnnotation(e, InheritedContainee.class));
}
static void inheritedMe8() {
AnnotatedElement e = Me8.class;
check(2 == e.getAnnotations().length);
check(2 == countAnnotation(e, InheritedContainee.class));
}
static void checkMultiplier(AnnotatedElement e, int m) {
// Basic sanity of non-repeating getAnnotation(Class)
check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
// Check count of annotations returned from getAnnotationsByType(Class)
check(4 == countAnnotation(e, Containee.class));
check(1 == countAnnotation(e, Container.class));
check(1 == countAnnotation(e, NonRepeated.class));
// Check contents of array returned from getAnnotationsByType(Class)
check(e.getAnnotationsByType(Containee.class)[2].value() == 3 * m);
check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 5 * m);
// Check getAnnotation(Class)
check(e.getAnnotation(Containee.class) == null);
check(e.getAnnotation(Container.class) != null);
// Check count of annotations returned from getAnnotations()
check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
check(1 == containsAnnotationOfType(e.getAnnotations(), Container.class));
check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class));
}
static void check(Boolean b) {
if (!b) throw new RuntimeException();
}
static int countAnnotation(AnnotatedElement e, Class<? extends Annotation> c) {
return containsAnnotationOfType(e.getAnnotationsByType(c), c);
}
static <A extends Annotation> int containsAnnotationOfType(A[] l, Class<? extends Annotation> a) {
int count = 0;
for (Annotation an : l) {
if (an.annotationType().equals(a))
count++;
}
return count;
}
}
@NonRepeated @InheritedNonRepeated
@InheritedContainee(1) @InheritedContainee(2) @InheritedContainee(3) @InheritedContainee(4)
@Containee(1) @Containee(2) @Containee(3) @Containee(4)
class Grandma {}
class Mother extends Grandma {}
@NonRepeated(5) @InheritedNonRepeated(15)
@InheritedContainee(150) @InheritedContainee(250) @InheritedContainee(350) @InheritedContainee(450)
@Containee(150) @Containee(250) @Containee(350) @Containee(450)
class Father extends Grandma {}
class Me1 extends Mother {
@NonRepeated(5)
@Containee(1) @Containee(2) @Containee(3) @Containee(4)
public String foo = "";
@NonRepeated(50)
@Containee(10) @Containee(20) @Containee(30) @Containee(40)
public Me1() {
}
@NonRepeated(500)
@Containee(100) @Containee(200) @Containee(300) @Containee(400)
public void mee() {
}
@NonRepeated(5000)
@Containee(1000) @Containee(2000) @Containee(3000) @Containee(4000)
public class MiniMee {}
@NonRepeated(500000)
@Containee(100000) @Containee(200000) @Containee(300000) @Containee(400000)
public enum E {
@NonRepeated(50000)
@Containee(10000) @Containee(20000) @Containee(30000) @Containee(40000)
EE(),
}
}
@NonRepeated(100) @InheritedNonRepeated(200)
@InheritedContainee(100) @InheritedContainee(200) @InheritedContainee(300) @InheritedContainee(400)
@Containee(100) @Containee(200) @Containee(300) @Containee(400)
class Me2 extends Mother {}
class Me3 extends Father {}
@NonRepeated(1000) @InheritedNonRepeated(2000)
@InheritedContainee(1000) @InheritedContainee(2000) @InheritedContainee(3000) @InheritedContainee(4000)
@Containee(1000) @Containee(2000) @Containee(3000) @Containee(4000)
class Me4 extends Father {}
@InheritedContainer({@InheritedContainee(1), @InheritedContainee(2)})
class SuperOf5 {}
@InheritedContainee(3)
class Me5 extends SuperOf5{}
@InheritedContainee(1) @InheritedContainee(2)
class SuperOf6 {}
@InheritedContainee(3)
class Me6 extends SuperOf6 {}
@InheritedContainee(1)
class SuperOf7 {}
@InheritedContainer({@InheritedContainee(2), @InheritedContainee(3)})
class Me7 extends SuperOf7 {}
@InheritedContainee(1)
class SuperOf8 {}
@InheritedContainee(2) @InheritedContainee(3)
class Me8 extends SuperOf8 {}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2012, 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.
*/
package subpackage;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Container.class)
public @interface Containee {
int value();
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2012, 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.
*/
package subpackage;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface Container {
Containee[] value();
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2012, 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.
*/
package subpackage;
import java.lang.annotation.*;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(InheritedContainer.class)
public @interface InheritedContainee {
int value();
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2012, 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.
*/
package subpackage;
import java.lang.annotation.*;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedContainer {
InheritedContainee[] value();
}

View file

@ -0,0 +1,31 @@
/*
* 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.
*/
package subpackage;
import java.lang.annotation.*;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedNonRepeated {
int value() default 20;
}

View file

@ -0,0 +1,30 @@
/*
* 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.
*/
package subpackage;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface NonRepeated {
int value() default 10;
}

View file

@ -0,0 +1,25 @@
/*
* 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.
*/
@NonRepeated @Containee(1) @Containee(2)
package subpackage;

View file

@ -0,0 +1,106 @@
/*
* 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 8023878
* @summary Test that the right kind of exception is thrown from the type
* annotation reflection code.
* @run testng BadCPIndex
*/
import java.lang.annotation.*;
import java.util.Base64;
import java.util.function.Function;
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
public class BadCPIndex {
private static final MyLoader loader = new MyLoader(BadCPIndex.class.getClassLoader());
// Blueprint for broken C
//public static class C extends @BadCPIndex.A Object {}
private static final String encodedBrokenC = "yv66vgAAADQAFgoAAwAPBwARBwATAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAClNvdXJjZUZpbGUBAA9CYWRDUEluZGV4LmphdmEBAB1SdW50aW1lVmlzaWJsZVR5cGVBbm5vdGF0aW9ucwcAFAEAAUEBAAxJbm5lckNsYXNzZXMBAA5MQmFkQ1BJbmRleCRBOwwABAAFBwAVAQAMQmFkQ1BJbmRleCRDAQABQwEAEGphdmEvbGFuZy9PYmplY3QBAAxCYWRDUEluZGV4JEEBAApCYWRDUEluZGV4ACEAAgADAAAAAAABAAEABAAFAAEABgAAAB0AAQABAAAABSq3AAGxAAAAAQAHAAAABgABAAAAKQADAAgAAAACAAkACgAAAAoAARD//wAADwAAAA0AAAASAAIACwAQAAwmCQACABAAEgAJ";
// Blueprint for broken D
//public static class D<@BadCPIndex.B U> {}
private static final String encodedBrokenD = "yv66vgAAADQAGAoAAwARBwATBwAVAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACVNpZ25hdHVyZQEAKDxVOkxqYXZhL2xhbmcvT2JqZWN0Oz5MamF2YS9sYW5nL09iamVjdDsBAApTb3VyY2VGaWxlAQAPQmFkQ1BJbmRleC5qYXZhAQAdUnVudGltZVZpc2libGVUeXBlQW5ub3RhdGlvbnMHABYBAAFCAQAMSW5uZXJDbGFzc2VzAQAOTEJhZENQSW5kZXgkQjsMAAQABQcAFwEADEJhZENQSW5kZXgkRAEAAUQBABBqYXZhL2xhbmcvT2JqZWN0AQAMQmFkQ1BJbmRleCRCAQAKQmFkQ1BJbmRleAAhAAIAAwAAAAAAAQABAAQABQABAAYAAAAdAAEAAQAAAAUqtwABsQAAAAEABwAAAAYAAQAAAEAABAAIAAAAAgAJAAoAAAACAAsADAAAAAkAAQAAAAARAAAADwAAABIAAgANABIADiYJAAIAEgAUAAk=";
// Blueprint for broken E
//public static class E extends @BadCPIndex.A Object {}
private static final String encodedBrokenE = "yv66vgAAADQAFgoAAwAPBwARBwATAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAClNvdXJjZUZpbGUBAA9CYWRDUEluZGV4LmphdmEBAB1SdW50aW1lVmlzaWJsZVR5cGVBbm5vdGF0aW9ucwcAFAEAAUEBAAxJbm5lckNsYXNzZXMBAA5MQmFkQ1BJbmRleCRBOwwABAAFBwAVAQAMQmFkQ1BJbmRleCRFAQABRQEAEGphdmEvbGFuZy9PYmplY3QBAAxCYWRDUEluZGV4JEEBAApCYWRDUEluZGV4ACEAAgADAAAAAAABAAEABAAFAAEABgAAAB0AAQABAAAABSq3AAGxAAAAAQAHAAAABgABAAAARgADAAgAAAACAAkACgAAAAoAARD//wAADgAKAA0AAAASAAIACwAQAAwmCQACABAAEgAJ";
private static final Object[][] cases = {
{ new Case("BadCPIndex$C", encodedBrokenC, Class::getAnnotatedSuperclass) },
{ new Case("BadCPIndex$D", encodedBrokenD, (c -> c.getTypeParameters()[0].getAnnotations()))},
{ new Case("BadCPIndex$E", encodedBrokenE, Class::getAnnotatedSuperclass) },
};
@DataProvider
public static Object[][] data() { return cases; }
@Test(dataProvider="data")
public static void testOpThrowsAFE(Case testCase) {
Class<?> c = loader.defineClass(testCase.name, Base64.getDecoder().decode(testCase.encoding));
try {
System.out.println("Testing: " + c);
testCase.trigger.apply(c);
throw new RuntimeException("Expecting AnnotationFormatError here");
} catch (AnnotationFormatError e) {
; //ok
} catch (Exception e) {
e.printStackTrace();
}
}
private static class MyLoader extends ClassLoader {
public MyLoader(ClassLoader parent) {
super(parent);
}
public Class<?> defineClass(String name, byte[] bytes) {
return defineClass(name, bytes, 0, bytes.length);
}
}
private static class Case {
public String name;
public String encoding;
public Function<Class<?>, Object> trigger;
public Case(String name, String encoding, Function<Class<?>, Object> trigger) {
this.name = name;
this.encoding = encoding;
this.trigger = trigger;
}
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public static @interface A {}
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public static @interface B {}
}

View file

@ -0,0 +1,177 @@
/*
* 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 8023651 8044629
* @summary Test that the receiver annotations and the return annotations of
* constructors behave correctly.
* @run testng ConstructorReceiverTest
*/
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.Arrays;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class ConstructorReceiverTest {
public static final Integer EMPTY_ANNOTATED_TYPE = Integer.valueOf(-1);
// Format is {
// { Class to get ctor for,
// ctor param class,
// value of anno of return type,
// value of anno for receiver,
// or null if there should be no receiver,
// or EMPTY_ANNOTATED_TYPE of there should be a receiver but
// no annotation
// },
// ...
// }
public static final Object[][] TESTS = {
{ ConstructorReceiverTest.class, null, Integer.valueOf(5), null },
{ ConstructorReceiverTest.Middle.class, ConstructorReceiverTest.class, Integer.valueOf(10), Integer.valueOf(15) },
{ ConstructorReceiverTest.Middle.Inner.class, ConstructorReceiverTest.Middle.class, Integer.valueOf(100), Integer.valueOf(150) },
{ ConstructorReceiverTest.Middle.Inner.Innermost.class, ConstructorReceiverTest.Middle.Inner.class, Integer.valueOf(1000), Integer.valueOf(1500) },
{ ConstructorReceiverTest.Middle.InnerNoReceiver.class, ConstructorReceiverTest.Middle.class, Integer.valueOf(300), EMPTY_ANNOTATED_TYPE },
{ ConstructorReceiverTest.Nested.class, null, Integer.valueOf(20), null },
{ ConstructorReceiverTest.Nested.NestedMiddle.class, ConstructorReceiverTest.Nested.class, Integer.valueOf(200), Integer.valueOf(250)},
{ ConstructorReceiverTest.Nested.NestedMiddle.NestedInner.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(2000), Integer.valueOf(2500)},
{ ConstructorReceiverTest.Nested.NestedMiddle.NestedInnerNoReceiver.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(4000), EMPTY_ANNOTATED_TYPE},
{ ConstructorReceiverTest.Nested.NestedMiddle.SecondNestedInnerNoReceiver.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(5000), EMPTY_ANNOTATED_TYPE},
};
@DataProvider
public Object[][] data() { return TESTS; }
@Test(dataProvider = "data")
public void testAnnotatedReciver(Class<?> toTest, Class<?> ctorParamType,
Integer returnVal, Integer receiverVal) throws NoSuchMethodException {
Constructor c;
if (ctorParamType == null)
c = toTest.getDeclaredConstructor();
else
c = toTest.getDeclaredConstructor(ctorParamType);
AnnotatedType annotatedReceiverType = c.getAnnotatedReceiverType();
// Some Constructors doesn't conceptually have a receiver, they should return null
if (receiverVal == null) {
assertNull(annotatedReceiverType, "getAnnotatedReciverType should return null for Constructor: " + c);
return;
}
// check that getType() matches the receiver (which can be parameterized)
if (annotatedReceiverType.getType() instanceof ParameterizedType) {
assertEquals(((ParameterizedType) annotatedReceiverType.getType()).getRawType(),
ctorParamType,
"getType() doesn't match receiver type: " + ctorParamType);
} else {
assertEquals(annotatedReceiverType.getType(),
ctorParamType,
"getType() doesn't match receiver type: " + ctorParamType);
}
Annotation[] receiverAnnotations = annotatedReceiverType.getAnnotations();
// Some Constructors have no annotations on but in theory can have a receiver
if (receiverVal.equals(EMPTY_ANNOTATED_TYPE)) {
assertEquals(receiverAnnotations.length, 0, "expecting an empty annotated type for: " + c);
return;
}
// The rest should have annotations
assertEquals(receiverAnnotations.length, 1, "expecting a 1 element array. Looking at 'length': ");
assertEquals(((Annot)receiverAnnotations[0]).value(), receiverVal.intValue(), " wrong annotation found. Found " +
receiverAnnotations[0] +
" should find @Annot with value=" +
receiverVal);
}
@Test(dataProvider = "data")
public void testAnnotatedReturn(Class<?> toTest, Class<?> ctorParamType,
Integer returnVal, Integer receiverVal) throws NoSuchMethodException {
Constructor c;
if (ctorParamType == null)
c = toTest.getDeclaredConstructor();
else
c = toTest.getDeclaredConstructor(ctorParamType);
AnnotatedType annotatedReturnType = c.getAnnotatedReturnType();
Annotation[] returnAnnotations = annotatedReturnType.getAnnotations();
assertEquals(returnAnnotations.length, 1, "expecting a 1 element array. Looking at 'length': ");
assertEquals(((Annot)returnAnnotations[0]).value(), returnVal.intValue(), " wrong annotation found. Found " +
returnAnnotations[0] +
" should find @Annot with value=" +
returnVal);
}
@Annot(5) ConstructorReceiverTest() {}
private class Middle {
@Annot(10) public Middle(@Annot(15) ConstructorReceiverTest ConstructorReceiverTest.this) {}
public class Inner {
@Annot(100) Inner(@Annot(150) Middle Middle.this) {}
class Innermost {
@Annot(1000) private Innermost(@Annot(1500) Inner Inner.this) {}
}
}
class InnerNoReceiver {
@Annot(300) InnerNoReceiver(Middle Middle.this) {}
}
}
public static class Nested {
@Annot(20) public Nested() {}
class NestedMiddle {
@Annot(200) public NestedMiddle(@Annot(250) Nested Nested.this) {}
class NestedInner {
@Annot(2000) public NestedInner(@Annot(2500) NestedMiddle NestedMiddle.this) {}
}
class NestedInnerNoReceiver {
@Annot(4000) public NestedInnerNoReceiver() {}
}
class SecondNestedInnerNoReceiver {
@Annot(5000) public SecondNestedInnerNoReceiver(NestedMiddle NestedMiddle.this) {}
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public static @interface Annot {
int value();
}
}

View file

@ -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 {}
abstract static class Clz {}
}

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2018, Google LLC. 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 8066967 8198526
* @summary Class.getAnnotatedSuperclass() does not correctly extract annotations
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.util.Arrays;
import java.util.Objects;
public class GetAnnotatedNestedSuperclass {
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface A {}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface B {}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface C {}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface D {}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface E {}
static class X<P1, P2, P3> {}
static class Y<P1, P2> extends @A X<@B P1, @C P2, @D Class<@E P1>> {}
public static void main(String[] args) throws Exception {
AnnotatedType x = Y.class.getAnnotatedSuperclass();
assertEquals(Arrays.toString(x.getAnnotations()), "[@GetAnnotatedNestedSuperclass.A()]");
AnnotatedParameterizedType xpt = (AnnotatedParameterizedType) x;
{
AnnotatedType arg = xpt.getAnnotatedActualTypeArguments()[0];
assertEquals(
Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass.B()]");
}
{
AnnotatedType arg = xpt.getAnnotatedActualTypeArguments()[1];
assertEquals(
Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass.C()]");
}
{
AnnotatedType arg = xpt.getAnnotatedActualTypeArguments()[2];
assertEquals(
Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass.D()]");
AnnotatedType nestedArg =
((AnnotatedParameterizedType) arg).getAnnotatedActualTypeArguments()[0];
assertEquals(
Arrays.toString(nestedArg.getAnnotations()),
"[@GetAnnotatedNestedSuperclass.E()]");
}
}
private static void assertEquals(Object actual, Object expected) {
if (!Objects.equals(expected, actual)) {
throw new AssertionError("expected: " + expected + "; actual=" + actual);
}
}
}

View file

@ -0,0 +1,340 @@
/*
* Copyright (c) 2015, 2018, 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 8058595
* @summary Test that AnnotatedType.getAnnotatedOwnerType() works as expected
*
* @library /test/lib
* @build jdk.test.lib.Asserts
* @run main GetAnnotatedOwnerType
*/
import java.lang.annotation.*;
import java.lang.reflect.*;
import jdk.test.lib.Asserts;
public class GetAnnotatedOwnerType<Dummy> {
public @TA("generic") GetAnnotatedOwnerType<String> . @TB("generic") Nested<Integer> genericField;
public @TA("raw") GetAnnotatedOwnerType . @TB("raw") Nested rawField;
public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("non-generic") Inner nonGeneric;
public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("generic") InnerGeneric<String> innerGeneric;
public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("raw") InnerGeneric innerRaw;
public GetAnnotatedOwnerTypeAuxilliary . @TB("non-generic") Nested nestedNonGeneric;
public GetAnnotatedOwnerTypeAuxilliary . @TB("generic") NestedGeneric<String> nestedGeneric;
public GetAnnotatedOwnerTypeAuxilliary . @TB("raw") NestedGeneric nestedRaw;
public Object anonymous = new Object() {};
public @TA("array") Dummy[] dummy;
public @TA("wildcard") GetAnnotatedOwnerType<?> wildcard;
public @TA("typevariable") Dummy tv;
public @TA("bad") GetAnnotatedOwnerType<@TA("good") GetAnnotatedOwnerType<String> . @TB("tb") Nested<Integer> > typeArgument;
public GetAnnotatedOwnerType< GetAnnotatedOwnerType<String> .
B .
C<Class<?>, ? extends @TA("complicated") Exception> .
D<Number> > [] complicated;
public static void main(String[] args) throws Exception {
testGeneric();
testRaw();
testNonGeneric();
testInnerGeneric();
testInnerRaw();
testNestedNonGeneric();
testNestedGeneric();
testNestedRaw();
testLocalClass();
testAnonymousClass();
testArray();
testWildcard();
testTypeParameter();
testTypeArgument();
testComplicated();
}
public static void testGeneric() throws Exception {
Field f = GetAnnotatedOwnerType.class.getField("genericField");
// make sure inner is correctly annotated
AnnotatedType inner = f.getAnnotatedType();
Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "generic");
Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ inner.getAnnotations().length);
// make sure owner is correctly annotated, on the correct type
AnnotatedType outer = inner.getAnnotatedOwnerType();
Asserts.assertEquals(outer.getType(), ((ParameterizedType) f.getGenericType()).getOwnerType());
Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "generic");
Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ outer.getAnnotations().length);
}
public static void testRaw() throws Exception {
Field f = GetAnnotatedOwnerType.class.getField("rawField");
// make sure inner is correctly annotated
AnnotatedType inner = f.getAnnotatedType();
Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "raw");
Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ inner.getAnnotations().length);
// make sure owner is correctly annotated, on the correct type
AnnotatedType outer = inner.getAnnotatedOwnerType();
Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "raw");
Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ outer.getAnnotations().length);
}
public static void testNonGeneric() throws Exception {
Field f = GetAnnotatedOwnerType.class.getField("nonGeneric");
// make sure inner is correctly annotated
AnnotatedType inner = f.getAnnotatedType();
Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "non-generic");
Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ inner.getAnnotations().length);
// make sure owner is correctly annotated, on the correct type
AnnotatedType outer = inner.getAnnotatedOwnerType();
Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ outer.getAnnotations().length);
}
public static void testInnerGeneric() throws Exception {
Field f = GetAnnotatedOwnerType.class.getField("innerGeneric");
// make sure inner is correctly annotated
AnnotatedType inner = f.getAnnotatedType();
Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "generic");
Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ inner.getAnnotations().length);
// make sure owner is correctly annotated, on the correct type
AnnotatedType outer = inner.getAnnotatedOwnerType();
Asserts.assertEquals(outer.getType(), ((ParameterizedType) f.getGenericType()).getOwnerType());
Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ outer.getAnnotations().length);
}
public static void testInnerRaw() throws Exception {
Field f = GetAnnotatedOwnerType.class.getField("innerRaw");
// make sure inner is correctly annotated
AnnotatedType inner = f.getAnnotatedType();
Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "raw");
Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ inner.getAnnotations().length);
// make sure owner is correctly annotated, on the correct type
AnnotatedType outer = inner.getAnnotatedOwnerType();
Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ outer.getAnnotations().length);
}
public static void testNestedNonGeneric() throws Exception {
Field f = GetAnnotatedOwnerType.class.getField("nestedNonGeneric");
// make sure inner is correctly annotated
AnnotatedType inner = f.getAnnotatedType();
Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "non-generic");
Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ inner.getAnnotations().length);
// make sure owner is correctly annotated, on the correct type
AnnotatedType outer = inner.getAnnotatedOwnerType();
Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
Asserts.assertTrue(outer.getAnnotations().length == 0, "expecting no annotations, got: "
+ outer.getAnnotations().length);
}
public static void testNestedGeneric() throws Exception {
Field f = GetAnnotatedOwnerType.class.getField("nestedGeneric");
// make sure inner is correctly annotated
AnnotatedType inner = f.getAnnotatedType();
Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "generic");
Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ inner.getAnnotations().length);
// make sure owner is correctly annotated, on the correct type
AnnotatedType outer = inner.getAnnotatedOwnerType();
Asserts.assertEquals(outer.getType(), ((ParameterizedType) f.getGenericType()).getOwnerType());
Asserts.assertTrue(outer.getAnnotations().length == 0, "expecting no annotations, got: "
+ outer.getAnnotations().length);
}
public static void testNestedRaw() throws Exception {
Field f = GetAnnotatedOwnerType.class.getField("nestedRaw");
// make sure inner is correctly annotated
AnnotatedType inner = f.getAnnotatedType();
Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "raw");
Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ inner.getAnnotations().length);
// make sure owner is correctly annotated, on the correct type
AnnotatedType outer = inner.getAnnotatedOwnerType();
Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
Asserts.assertTrue(outer.getAnnotations().length == 0, "expecting no annotations, got: "
+ outer.getAnnotations().length);
}
public static void testLocalClass() throws Exception {
class ALocalClass {}
class OneMore {
public @TA("null") ALocalClass c;
}
testNegative(OneMore.class.getField("c").getAnnotatedType(), "Local class should return null");
}
public static void testAnonymousClass() throws Exception {
testNegative(GetAnnotatedOwnerType.class.getField("anonymous").getAnnotatedType(),
"Anonymous class should return null");
}
public static void testArray() throws Exception {
AnnotatedType t = GetAnnotatedOwnerType.class.getField("dummy").getAnnotatedType();
Asserts.assertTrue((t instanceof AnnotatedArrayType),
"Was expecting an AnnotatedArrayType " + t);
testNegative(t, "" + t + " should not have an annotated owner type");
}
public static void testWildcard() throws Exception {
AnnotatedType tt = GetAnnotatedOwnerType.class.getField("wildcard").getAnnotatedType();
AnnotatedType t = ((AnnotatedParameterizedType)tt).getAnnotatedActualTypeArguments()[0];
Asserts.assertTrue((t instanceof AnnotatedWildcardType),
"Was expecting an AnnotatedWildcardType " + t);
testNegative(t, "" + t + " should not have an annotated owner type");
}
public static void testTypeParameter() throws Exception {
AnnotatedType t = GetAnnotatedOwnerType.class.getField("tv").getAnnotatedType();
Asserts.assertTrue((t instanceof AnnotatedTypeVariable),
"Was expecting an AnnotatedTypeVariable " + t);
testNegative(t, "" + t + " should not have an annotated owner type");
}
public static void testTypeArgument() throws Exception {
AnnotatedType tt = GetAnnotatedOwnerType.class.getField("typeArgument").getAnnotatedType();
Asserts.assertEquals(tt.getAnnotation(TA.class).value(), "bad");
Asserts.assertTrue(tt.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ tt.getAnnotations().length);
// make sure inner is correctly annotated
AnnotatedType inner = ((AnnotatedParameterizedType)tt).getAnnotatedActualTypeArguments()[0];
Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "tb");
Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ inner.getAnnotations().length);
// make sure owner is correctly annotated
AnnotatedType outer = inner.getAnnotatedOwnerType();
Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "good");
Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ outer.getAnnotations().length);
}
public static void testComplicated() throws Exception {
Field f = GetAnnotatedOwnerType.class.getField("complicated");
// Outermost level
AnnotatedType t = f.getAnnotatedType();
Asserts.assertTrue((t instanceof AnnotatedArrayType),
"Was expecting an AnnotatedArrayType " + t);
testNegative(t, "" + t + " should not have an annotated owner type");
Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ t.getAnnotations().length);
// Component type
t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType();
testNegative(t, "" + t + " should not have an annotated owner type");
Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ t.getAnnotations().length);
// Type arg GetAnnotatedOwnerType<String>...D<Number>
t = ((AnnotatedParameterizedType)t).getAnnotatedActualTypeArguments()[0];
Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ t.getAnnotations().length);
// C<Class<?>, ? extends ...>
t = t.getAnnotatedOwnerType();
Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ t.getAnnotations().length);
// ? extends
t = ((AnnotatedParameterizedType)t).getAnnotatedActualTypeArguments()[1];
testNegative(t, "" + t + " should not have an annotated owner type");
Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ t.getAnnotations().length);
// @TA("complicated") Exception
t = ((AnnotatedWildcardType)t).getAnnotatedUpperBounds()[0];
testNegative(t, "" + t + " should not have an annotated owner type");
Asserts.assertEquals(t.getAnnotation(TA.class).value(), "complicated");
Asserts.assertTrue(t.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ t.getAnnotations().length);
}
private static void testNegative(AnnotatedType t, String msg) {
Asserts.assertNull(t.getAnnotatedOwnerType(), msg);
}
public class Nested<AlsoDummy> {}
public class B {
public class C<R, S> {
public class D<T> {
}
}
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TA {
String value();
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TB {
String value();
}
}
class GetAnnotatedOwnerTypeAuxilliary {
class Inner {}
class InnerGeneric<Dummy> {}
static class Nested {}
static class NestedGeneric<Dummy> {}
}

View file

@ -0,0 +1,240 @@
/*
* Copyright (c) 2013, 2014, 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 8044629 8256693
*/
import java.lang.reflect.*;
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) {}
}
public static class Nested {
public Nested() {}
public class NestedInner {
public NestedInner() { }
public Class<?> getLocalClass () {
class NestedInnerLocal { public NestedInnerLocal() {} }
return NestedInnerLocal.class;
}
public Class<?> getAnonymousClass() {
return new Object() {}.getClass();
}
}
}
public class Inner2 {
public Inner2() { }
public void innerMethod2(GetAnnotatedReceiverType.Inner2 this) {}
public class Inner3 {
public Inner3() { }
public void innerMethod3(GetAnnotatedReceiverType.Inner2.Inner3 this) {}
public class Inner7<T> {
public void innerMethod7(GetAnnotatedReceiverType.Inner2.Inner3.Inner7<T> this) {}
}
public Class<?> getLocalClass () {
class InnerLocal { public InnerLocal() {} }
return InnerLocal.class;
}
public Class<?> getAnonymousClass() {
return new Object() {}.getClass();
}
}
public Class<?> getLocalClass () {
class InnerLocal { public InnerLocal() {} }
return InnerLocal.class;
}
public Class<?> getAnonymousClass() {
return new Object() {}.getClass();
}
}
public class Inner4<T> {
public Inner4(GetAnnotatedReceiverType GetAnnotatedReceiverType.this) {}
public void innerMethod4(GetAnnotatedReceiverType.Inner4<T> this) {}
public class Inner5 {
public Inner5(GetAnnotatedReceiverType.Inner4<T> GetAnnotatedReceiverType.Inner4.this) {}
public void innerMethod5(GetAnnotatedReceiverType.Inner4<T>.Inner5 this) {}
public class Inner6 {
public Inner6(GetAnnotatedReceiverType.Inner4<T>.Inner5 GetAnnotatedReceiverType.Inner4.Inner5.this) {}
}
}
}
private static int failures = 0;
private static int tests = 0;
private static final int EXPECTED_TEST_CASES = 25;
public static void main(String[] args) throws NoSuchMethodException {
checkEmptyAT(GetAnnotatedReceiverType.class.getMethod("method"),
"getAnnotatedReceiverType for \"method\" should return an empty AnnotatedType");
checkEmptyAT(Inner0.class.getConstructor(GetAnnotatedReceiverType.class),
"getAnnotatedReceiverType for a ctor without a \"this\" should return an empty AnnotatedType");
checkEmptyAT(GetAnnotatedReceiverType.class.getMethod("method0"),
"getAnnotatedReceiverType for \"method0\" should return an empty AnnotatedType");
checkEmptyAT(Inner1.class.getConstructor(GetAnnotatedReceiverType.class),
"getAnnotatedReceiverType for a ctor with a \"this\" should return an empty AnnotatedType");
checkNull(GetAnnotatedReceiverType.class.getMethod("method4"),
"getAnnotatedReceiverType() on a static method should return null");
// More nested, inner, local and anonymous classes
Nested nested = new Nested();
Nested.NestedInner instance = nested.new NestedInner();
checkNull(nested.getClass().getConstructors()[0],
"getAnnotatedReceiverType() on a constructor for a static class should return null");
checkEmptyAT(instance.getClass().getConstructors()[0],
"getAnnotatedReceiverType for a ctor without a \"this\" should return an empty AnnotatedType");
checkNull(instance.getLocalClass().getConstructors()[0],
"getAnnotatedReceiverType() on a constructor for a local class should return null");
checkNull(instance.getAnonymousClass().getDeclaredConstructors()[0],
"getAnnotatedReceiverType() on a constructor for an anonymous class should return null");
GetAnnotatedReceiverType outer = new GetAnnotatedReceiverType();
Inner2 instance2 = outer.new Inner2();
checkEmptyAT(instance2.getClass().getConstructors()[0],
"getAnnotatedReceiverType for a ctor without a \"this\" should return an empty AnnotatedType");
checkNull(instance2.getLocalClass().getConstructors()[0],
"getAnnotatedReceiverType() on a constructor for a local class should return null");
checkNull(instance2.getAnonymousClass().getDeclaredConstructors()[0],
"getAnnotatedReceiverType() on a constructor for an anonymous class should return null");
Inner2.Inner3 instance3 = instance2.new Inner3();
checkEmptyAT(instance3.getClass().getConstructors()[0],
"getAnnotatedReceiverType for a ctor without a \"this\" should return an empty AnnotatedType");
checkNull(instance3.getLocalClass().getConstructors()[0],
"getAnnotatedReceiverType() on a constructor for a local class should return null");
checkNull(instance3.getAnonymousClass().getDeclaredConstructors()[0],
"getAnnotatedReceiverType() on a constructor for an anonymous class should return null");
Inner4<?> instance4 = outer.new Inner4<String>();
Inner4<?>.Inner5 instance5 = instance4.new Inner5();
Inner4<?>.Inner5.Inner6 instance6 = instance5.new Inner6();
checkAnnotatedReceiverType(instance4.getClass().getConstructors()[0], false,
"The type of .getAnnotatedReceiverType().getType() for this constructor should be");
checkAnnotatedReceiverType(instance5.getClass().getConstructors()[0], true,
"The type of .getAnnotatedReceiverType().getType() for this constructor should be");
checkAnnotatedReceiverType(instance6.getClass().getConstructors()[0], true,
"The type of .getAnnotatedReceiverType().getType() for this constructor should be");
checkAnnotatedReceiverType(outer.getClass().getMethod("method0"), false,
"The type of .getAnnotatedReceiverType().getType() for this method should be");
checkAnnotatedReceiverType(instance4.getClass().getMethod("innerMethod4"), true,
"The type of .getAnnotatedReceiverType().getType() for this method should be");
checkAnnotatedReceiverType(instance5.getClass().getMethod("innerMethod5"), true,
"The type of .getAnnotatedReceiverType().getType() for this method should be");
checkAnnotatedReceiverType(instance2.getClass().getMethod("innerMethod2"), false,
"The type of .getAnnotatedReceiverType().getType() for this method should be");
checkAnnotatedReceiverType(instance3.getClass().getMethod("innerMethod3"), false,
"The type of .getAnnotatedReceiverType().getType() for this method should be");
Inner2.Inner3.Inner7<?> instance7 = instance3.new Inner7<String>();
checkAnnotatedReceiverType(instance7.getClass().getMethod("innerMethod7"), true,
"The type of .getAnnotatedReceiverType().getType() for this method should be");
recursiveCheckAnnotatedOwnerTypes(instance7.getClass().getMethod("innerMethod7").getAnnotatedReceiverType());
if (failures != 0)
throw new RuntimeException("Test failed, see log for details");
else if (tests != EXPECTED_TEST_CASES)
throw new RuntimeException("Not all cases ran, failing");
}
private static void checkNull(Executable e, String msg) {
AnnotatedType a = e.getAnnotatedReceiverType();
if (a != null) {
failures++;
System.err.println(msg + ": " + e);
}
tests++;
}
private static void checkEmptyAT(Executable e, String msg) {
AnnotatedType a = e.getAnnotatedReceiverType();
if (a.getAnnotations().length != 0) {
failures++;
System.err.print(msg + ": " + e);
}
tests++;
}
private static void checkAnnotatedReceiverType(Executable e, boolean shouldBeParameterized, String msg) {
Type t = e.getAnnotatedReceiverType().getType();
if (shouldBeParameterized != (t instanceof ParameterizedType)) {
failures++;
System.err.println(e + ", " + msg + " " + (shouldBeParameterized ? "ParameterizedType" : "Class") + ", found: " + t.getClass().getSimpleName());
}
// Test we can get the potentially empty annotated actual type arguments array
if (shouldBeParameterized) {
try {
ParameterizedType t1 = (ParameterizedType)t;
AnnotatedParameterizedType at1 = (AnnotatedParameterizedType)e.getAnnotatedReceiverType();
if (t1.getActualTypeArguments().length != at1.getAnnotatedActualTypeArguments().length) {
System.err.println(t1 + "'s actual type arguments can't match " + at1);
failures++;
}
} catch (ClassCastException cce) {
System.err.println("Couldn't get potentially empty actual type arguments: " + cce.getMessage());
failures++;
}
}
tests++;
}
private static void recursiveCheckAnnotatedOwnerTypes(AnnotatedType t) {
AnnotatedType check = t.getAnnotatedOwnerType();
do {
if (!(check.getType() instanceof Class<?>)) {
failures++;
System.err.println("Expecting only instances of Class returned for .getType() found " + check.getType().getClass().getSimpleName());
}
check = check.getAnnotatedOwnerType();
} while (check != null);
tests++;
}
}

View file

@ -0,0 +1,98 @@
/*
* 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 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<?>[] nullTestData = {
Object.class,
If.class,
Object[].class,
void.class,
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 {
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) {
failed++;
System.out.println(toTest + ".getAnnotatedSuperclass() returns: "
+ res + ", should be null");
}
}
}
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 {}
abstract static class Clz {}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016, 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.
*/
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface MissingAnnotation { }

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2016, 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 8152174
* @summary Verify that a missing class file for a type use annotation doesn't cause a NPE when attempting to read the annotation.
* @compile NoNpeOnMissingAnnotation.java MissingAnnotation.java
* @run main NoNpeOnMissingAnnotation
* @clean MissingAnnotation
* @run main NoNpeOnMissingAnnotation
*/
import java.lang.annotation.*;
public class NoNpeOnMissingAnnotation {
public static void main(String... args) throws Exception {
System.out.println(NoNpeOnMissingAnnotation.class.
getDeclaredMethod("foo").
getAnnotatedReturnType());
}
@MissingAnnotation Object foo() { return null; }
}

View file

@ -0,0 +1,147 @@
/*
* Copyright (c) 2020, 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 8202469
* @summary Test adjustment of type bound index if no explicit class bound is defined
* @compile ParameterizedBoundIndex.java
* @run main ParameterizedBoundIndex
*/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
/*
* According to JVMS 4.3.4, the first bound of a parameterized type is
* taken to be Object, if no explicit class bound is specified. As a
* consequence, the first interface's bound is always 1, independently
* of an explicit class bound.
*
* This test investigates if this mismatch between explicit and actual
* type bound index is accounted for.
*/
public class ParameterizedBoundIndex {
public static void main(String[] args) throws Exception {
List<Class<?>> failed = new ArrayList<>();
if (!TypeClassBound.class.getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(TypeClassBound.class);
}
if (!TypeInterfaceBound.class.getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(TypeInterfaceBound.class);
}
if (!TypeParameterizedInterfaceBound.class.getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(TypeParameterizedInterfaceBound.class);
}
if (!TypeParameterizedClassBound.class.getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(TypeParameterizedClassBound.class);
}
if (!TypeVariableBound.class.getTypeParameters()[1].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(TypeVariableBound.class);
}
if (!MethodClassBound.class.getDeclaredMethod("m").getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(MethodClassBound.class);
}
if (!MethodInterfaceBound.class.getDeclaredMethod("m").getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(MethodInterfaceBound.class);
}
if (!MethodParameterizedInterfaceBound.class.getDeclaredMethod("m").getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(MethodParameterizedInterfaceBound.class);
}
if (!MethodParameterizedClassBound.class.getDeclaredMethod("m").getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(MethodParameterizedClassBound.class);
}
if (!MethodVariableBound.class.getDeclaredMethod("m").getTypeParameters()[1].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(MethodVariableBound.class);
}
if (!ConstructorClassBound.class.getDeclaredConstructor().getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(ConstructorClassBound.class);
}
if (!ConstructorInterfaceBound.class.getDeclaredConstructor().getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(ConstructorInterfaceBound.class);
}
if (!ConstructorParameterizedInterfaceBound.class.getDeclaredConstructor().getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(ConstructorParameterizedInterfaceBound.class);
}
if (!ConstructorParameterizedClassBound.class.getDeclaredConstructor().getTypeParameters()[0].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(ConstructorParameterizedClassBound.class);
}
if (!ConstructorVariableBound.class.getDeclaredConstructor().getTypeParameters()[1].getAnnotatedBounds()[0].isAnnotationPresent(TypeAnnotation.class)) {
failed.add(ConstructorVariableBound.class);
}
if (!failed.isEmpty()) {
throw new RuntimeException("Failed: " + failed);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface TypeAnnotation { }
static class TypeClassBound<T extends @TypeAnnotation Void> { }
static class TypeInterfaceBound<T extends @TypeAnnotation Runnable> { }
static class TypeParameterizedInterfaceBound<T extends @TypeAnnotation List<?>> { }
static class TypeParameterizedClassBound<T extends @TypeAnnotation ArrayList<?>> { }
static class TypeVariableBound<T, S extends @TypeAnnotation T> { }
static class MethodClassBound<T extends @TypeAnnotation Void> {
<T extends @TypeAnnotation Void> void m() { }
}
static class MethodInterfaceBound {
<T extends @TypeAnnotation Runnable> void m() { }
}
static class MethodParameterizedInterfaceBound<T extends @TypeAnnotation List<?>> {
<T extends @TypeAnnotation List<?>> void m() { }
}
static class MethodParameterizedClassBound {
<T extends @TypeAnnotation ArrayList<?>> void m() { }
}
static class MethodVariableBound<T, S extends @TypeAnnotation T> {
<T, S extends @TypeAnnotation T> void m() { }
}
static class ConstructorClassBound<T extends @TypeAnnotation Void> {
<T extends @TypeAnnotation Void> ConstructorClassBound() { }
}
static class ConstructorInterfaceBound {
<T extends @TypeAnnotation Runnable> ConstructorInterfaceBound() { }
}
static class ConstructorParameterizedInterfaceBound<T extends @TypeAnnotation List<?>> {
<T extends @TypeAnnotation List<?>> ConstructorParameterizedInterfaceBound() { }
}
static class ConstructorParameterizedClassBound {
<T extends @TypeAnnotation ArrayList<?>> ConstructorParameterizedClassBound() { }
}
static class ConstructorVariableBound<T, S extends @TypeAnnotation T> {
<T, S extends @TypeAnnotation T> ConstructorVariableBound() { }
}
}

View file

@ -0,0 +1,232 @@
/*
* Copyright (c) 2017, 2022, 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 8074977
* @summary Test consistency of annotations on constructor parameters
* @compile TestConstructorParameterTypeAnnotations.java
* @run main TestConstructorParameterTypeAnnotations
* @compile -parameters TestConstructorParameterTypeAnnotations.java
* @run main TestConstructorParameterTypeAnnotations
*/
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
/*
* Some constructor parameters are <em>mandated</em>; that is, they
* are not explicitly present in the source code, but required to be
* present by the Java Language Specification. In other cases, some
* constructor parameters are not present in the source, but are
* synthesized by the compiler as an implementation artifact. There is
* not a reliable mechanism to consistently determine whether or not
* a parameter is implicit or not.
*
* (Using the "-parameters" option to javac does emit the information
* needed to make a reliably determination, but the information is not
* present by default.)
*
* The lack of such a mechanism causes complications reading parameter
* annotations in some cases since annotations for parameters are
* written out for the parameters in the source code, but when reading
* annotations at runtime all the parameters, including implicit ones,
* are present.
*/
public class TestConstructorParameterTypeAnnotations {
public static void main(String... args) {
int errors = 0;
Class<?>[] classes = {NestedClass0.class,
NestedClass1.class,
NestedClass2.class,
NestedClass3.class,
NestedClass4.class,
StaticNestedClass0.class,
StaticNestedClass1.class,
StaticNestedClass2.class };
for (Class<?> clazz : classes) {
for (Constructor<?> ctor : clazz.getConstructors()) {
System.out.println(ctor);
errors += checkGetParameterAnnotations(clazz, ctor);
errors += checkGetAnnotatedParametersGetAnnotation(clazz, ctor);
}
}
if (errors > 0)
throw new RuntimeException(errors + " errors.");
return;
}
private static int checkGetParameterAnnotations(Class<?> clazz,
Constructor<?> ctor) {
String annotationString =
Arrays.deepToString(ctor.getParameterAnnotations());
String expectedString =
clazz.getAnnotation(ExpectedGetParameterAnnotations.class).value();
if (!Objects.equals(annotationString, expectedString)) {
System.err.println("Annotation mismatch on " + ctor +
"\n\tExpected:" + expectedString +
"\n\tActual: " + annotationString);
return 1;
}
return 0;
}
private static int checkGetAnnotatedParametersGetAnnotation(Class<?> clazz,
Constructor<?> ctor) {
int errors = 0;
int i = 0;
ExpectedParameterTypeAnnotations epa =
clazz.getAnnotation(ExpectedParameterTypeAnnotations.class);
for (AnnotatedType param : ctor.getAnnotatedParameterTypes() ) {
String annotationString =
Objects.toString(param.getAnnotation(MarkerTypeAnnotation.class));
String expectedString = epa.value()[i];
if (!Objects.equals(annotationString, expectedString)) {
System.err.println("Annotation mismatch on " + ctor +
" on param " + param +
"\n\tExpected:" + expectedString +
"\n\tActual: " + annotationString);
errors++;
}
i++;
}
return errors;
}
@ExpectedGetParameterAnnotations("[[]]")
@ExpectedParameterTypeAnnotations({"null"})
public class NestedClass0 {
public NestedClass0() {}
}
@ExpectedGetParameterAnnotations("[[], []]")
@ExpectedParameterTypeAnnotations({
"null",
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(1)"})
public class NestedClass1 {
public NestedClass1(@MarkerTypeAnnotation(1) int parameter) {}
}
@ExpectedGetParameterAnnotations("[[], [], []]")
@ExpectedParameterTypeAnnotations({
"null",
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(2)",
"null"})
public class NestedClass2 {
public NestedClass2(@MarkerTypeAnnotation(2) int parameter1,
int parameter2) {}
}
@ExpectedGetParameterAnnotations("[[], [], []]")
@ExpectedParameterTypeAnnotations({
"null",
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(3)",
"null"})
public class NestedClass3 {
public <P> NestedClass3(@MarkerTypeAnnotation(3) P parameter1,
int parameter2) {}
}
@ExpectedGetParameterAnnotations("[[], [], []]")
@ExpectedParameterTypeAnnotations({
"null",
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(4)",
"null"})
public class NestedClass4 {
public <P, Q> NestedClass4(@MarkerTypeAnnotation(4) P parameter1,
Q parameter2) {}
}
@ExpectedGetParameterAnnotations("[]")
@ExpectedParameterTypeAnnotations({"null"})
public static class StaticNestedClass0 {
public StaticNestedClass0() {}
}
@ExpectedGetParameterAnnotations("[[]]")
@ExpectedParameterTypeAnnotations({
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(1)"})
public static class StaticNestedClass1 {
public StaticNestedClass1(@MarkerTypeAnnotation(1) int parameter) {}
}
@ExpectedGetParameterAnnotations("[[], []]")
@ExpectedParameterTypeAnnotations({
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(2)",
"null"})
public static class StaticNestedClass2 {
public StaticNestedClass2(@MarkerTypeAnnotation(2) int parameter1,
int parameter2) {}
}
@ExpectedGetParameterAnnotations("[[], []]")
@ExpectedParameterTypeAnnotations({
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(3)",
"null"})
public static class StaticNestedClass3 {
public <P> StaticNestedClass3(@MarkerTypeAnnotation(3) P parameter1,
int parameter2) {}
}
@ExpectedGetParameterAnnotations("[[], []]")
@ExpectedParameterTypeAnnotations({
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(4)",
"null"})
public static class StaticNestedClass4 {
public <P, Q> StaticNestedClass4(@MarkerTypeAnnotation(4) P parameter1,
Q parameter2) {}
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface MarkerTypeAnnotation {
int value();
}
/**
* String form of expected value of calling
* getParameterAnnotations on a constructor.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface ExpectedGetParameterAnnotations {
String value();
}
/**
* String form of expected value of calling
* getAnnotation(MarkerTypeAnnotation.class) on each element of the
* result of getParameters() on a constructor.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface ExpectedParameterTypeAnnotations {
String[] value();
}
}

View file

@ -0,0 +1,284 @@
/*
* Copyright (c) 2014, 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 8039916
* @summary Test that a call to getType() on an AnnotatedType returned from an
* Executable.getAnnotated* returns the same type as the corresponding
* Executable.getGeneric* call.
* @run testng TestExecutableGetAnnotatedType
*/
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.testng.Assert.*;
public class TestExecutableGetAnnotatedType {
@Test(dataProvider = "genericExecutableData")
public void testGenericMethodExceptions(Executable e) throws Exception {
testExceptions(e);
}
@Test(dataProvider = "executableData")
public void testMethodExceptions(Executable e) throws Exception {
testExceptions(e);
}
@Test(dataProvider = "genericExecutableData")
public void testGenericMethodParameterTypes(Executable e) throws Exception {
testMethodParameters(e);
}
@Test(dataProvider = "executableData")
public void testMethodParameterTypes(Executable e) throws Exception {
testMethodParameters(e);
}
@Test(dataProvider = "genericExecutableData")
public void testGenericParameterTypes(Executable e) throws Exception {
testParameters(e.getParameters());
}
@Test(dataProvider = "executableData")
public void testParameterTypes(Executable e) throws Exception {
testParameters(e.getParameters());
}
@Test(dataProvider = "genericMethodData")
public void testGenericReceiverType(Executable e) throws Exception {
testParameterizedReceiverType0(e);
}
@Test(dataProvider = "methodData")
public void testReceiverType(Executable e) throws Exception {
testReceiverType0(e);
}
@Test(dataProvider = "genericMethodData")
public void testGenericMethodReturnType(Object o) throws Exception {
// testng gets confused if the param to this method has type Method
Method m = (Method)o;
testReturnType(m);
}
@Test(dataProvider = "methodData")
public void testMethodReturnType(Object o) throws Exception {
// testng gets confused if the param to this method has type Method
Method m = (Method)o;
testReturnType(m);
}
private void testExceptions(Executable e) {
Type[] ts = e.getGenericExceptionTypes();
AnnotatedType[] ats = e.getAnnotatedExceptionTypes();
assertEquals(ts.length, ats.length);
for (int i = 0; i < ts.length; i++) {
Type t = ts[i];
AnnotatedType at = ats[i];
assertSame(at.getType(), t, e.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
}
}
private void testMethodParameters(Executable e) {
Type[] ts = e.getGenericParameterTypes();
AnnotatedType[] ats = e.getAnnotatedParameterTypes();
assertEquals(ts.length, ats.length);
for (int i = 0; i < ts.length; i++) {
Type t = ts[i];
AnnotatedType at = ats[i];
assertSame(at.getType(), t, e.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
}
}
private void testParameters(Parameter[] params) {
for (Parameter p : params) {
Type t = p.getParameterizedType();
AnnotatedType at = p.getAnnotatedType();
assertSame(at.getType(), t, p.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
}
}
private void testReceiverType0(Executable e) {
if (Modifier.isStatic(e.getModifiers()))
assertNull(e.getAnnotatedReceiverType());
else
assertSame(e.getAnnotatedReceiverType().getType(), e.getDeclaringClass());
}
private void testParameterizedReceiverType0(Executable e) {
if (Modifier.isStatic(e.getModifiers()))
assertNull(e.getAnnotatedReceiverType());
else {
assertTrue(e.getAnnotatedReceiverType().getType() instanceof ParameterizedType);
assertSame(((ParameterizedType) e.getAnnotatedReceiverType().getType()).getRawType(), e.getDeclaringClass());
}
}
private void testReturnType(Method m) {
Type t = m.getGenericReturnType();
AnnotatedType at = m.getAnnotatedReturnType();
assertSame(at.getType(), t, m.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
}
@DataProvider
public Object[][] methodData() throws Exception {
return filterData(Arrays.stream(Methods1.class.getMethods()), Methods1.class)
.toArray(new Object[0][0]);
}
@DataProvider
public Object[][] genericMethodData() throws Exception {
return filterData(Arrays.stream(GenericMethods1.class.getMethods()), GenericMethods1.class)
.toArray(new Object[0][0]);
}
@DataProvider
public Object[][] executableData() throws Exception {
@SuppressWarnings("raw")
List l = filterData(Arrays.stream(Methods1.class.getMethods()), Methods1.class);
l.addAll(filterData(Arrays.stream(Methods1.class.getConstructors()), Methods1.class));
l.addAll(filterData(Arrays.stream(Ctors1.class.getConstructors()), Ctors1.class));
return ((List<Object[][]>)l).toArray(new Object[0][0]);
}
@DataProvider
public Object[][] genericExecutableData() throws Exception {
@SuppressWarnings("raw")
List l = filterData(Arrays.stream(GenericMethods1.class.getMethods()), GenericMethods1.class);
l.addAll(filterData(Arrays.stream(GenericMethods1.class.getConstructors()), GenericMethods1.class));
l.addAll(filterData(Arrays.stream(GenericCtors1.class.getConstructors()), GenericCtors1.class));
return ((List<Object[][]>)l).toArray(new Object[0][0]);
}
private List<?> filterData(Stream<? extends Executable> l, Class<?> c) {
return l.filter(m -> (m.getDeclaringClass() == c)) // remove object methods
.map(m -> { Object[] o = new Object[1]; o[0] = m; return o; })
.collect(Collectors.toList());
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface TA {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface TB {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface TC {}
public static class Methods1 {
public static void m1() throws Error, RuntimeException {;}
public static long m2(int a, double b) throws Error, RuntimeException { return 0L; }
public static Object m3(String s, List l) throws Error, RuntimeException { return null; }
public static Object m4(String s, List<String> l) { return null; }
public static Object m4(String s, List<String> l, boolean ... b){ return null; }
public static void m10() throws @TA Error, @TB @TC RuntimeException {;}
public static @TB long m20(@TC int a, @TA double b) throws @TA Error, @TB @TC RuntimeException { return 0L; }
public static @TC Object m30(@TA String s, @TB List l) throws @TA Error, @TB @TC RuntimeException { return null; }
public static @TA Object m40(@TB String s, @TC List<@TA String> l) { return null; }
public static @TA Object m40(@TB String s, @TC List<@TA String> l, @TB boolean ... b) { return null; }
public Methods1(int a, double b) {}
public Methods1(String s, List<String> l, boolean ... b) {}
public Methods1(@TC long a, @TA float b) {}
public Methods1(@TA int i, @TB String s, @TC List<@TA String> l, @TB boolean ... b) {}
}
// test default ctor
public static class Ctors1 {
}
public static class GenericMethods1<E> {
public E m1(E e, Object o) throws Error, RuntimeException { return null; }
public E m2(List<? extends List> e, int i) throws Error, RuntimeException { return null; }
public E m3(double d, List<E> e) throws Error, RuntimeException { return null; }
public <E extends List> E m4(byte[] b, GenericMethods1<? extends E> e) { return null; }
public <E extends List> E m5(GenericMethods1<? super Number> e) { return null; }
public <E extends List & Cloneable> E m6(char c, E e) { return null; }
public <E extends List & Cloneable> E m7(char c, E e, byte ... b) { return null; }
public static <M> M n1(M e) { return null; }
public static <M> M n2(List<? extends List> e) { return null; }
public static <M extends RuntimeException> M n3(List<M> e) throws Error, M { return null; }
public static <M extends Number> M n4(GenericMethods1<? extends M> e) throws Error, RuntimeException { return null; }
public static <M extends Object> M n5(GenericMethods1<? super Number> e) { return null; }
public static <M extends List & Cloneable> M n6(M e) { return null; }
public <M> E o1(E e) { return null; }
public <M> E o2(List<? extends List> e) { return null; }
public <M extends Error, N extends RuntimeException> E o3(GenericMethods1<E> this, List<E> e) throws M, N { return null; }
public <M extends Number> E o4(GenericMethods1<? extends E> e) throws Error, RuntimeException { return null; }
public <M extends Object> E o5(GenericMethods1<? super Number> e) { return null; }
public <M extends List & Cloneable> E o6(E e) { return null; }
// with annotations
public @TA E m10(E e, @TC Object o) throws @TA Error, @TB @TC RuntimeException { return null; }
public @TB E m20(@TA List<@TA ? extends @TA List> e, @TC int i) throws @TA Error, @TB @TC RuntimeException { return null; }
public @TB E m30(@TC double d, List<E> e) throws @TA Error, @TB @TC RuntimeException { return null; }
public <@TA E extends @TA List> @TA E m40(@TA byte @TB [] b, GenericMethods1<@TA ? extends E> e) { return null; }
public <@TB E extends @TB List> E m50(@TA GenericMethods1<? super Number> e) { return null; }
public <@TB E extends @TA List & Cloneable> E m60(@TC char c, E e) { return null; }
public <@TB E extends @TA List & Cloneable> E m70(@TC char c, E e, @TA @TB byte ... b) { return null; }
public static <@TA M> @TA M n10(M e) { return null; }
public static <@TA @TB @TC M> M n20(List<@TA ? extends List> e) { return null; }
@TA @TB @TC public static <M extends RuntimeException> M n30(List<@TB M> e) throws @TA Error, @TB @TC M { return null; }
public static <@TC M extends Number> M n40(GenericMethods1<? extends @TA M> e) throws @TA Error, @TB @TC RuntimeException { return null; }
@TA public static <M extends @TB Object> M n50(GenericMethods1<? super Number> e) { return null; }
public static <@TA M extends @TB List & @TC @TB Cloneable> M n60(M e) { return null; }
public <@TC M> E o10(@TA E e) { return null; }
public <M> @TA E o20(@TB List<@TB ? extends @TB List> e) { return null; }
@TC public <M extends Error, N extends RuntimeException> @TB E o30(@TA @TB @TC GenericMethods1<E> this, List<E> e) throws @TA M, @TB @TC N { return null; }
public <@TA M extends Number> E o40(GenericMethods1<? extends @TA E> e) throws @TA Error, @TB @TC RuntimeException { return null; }
public <M extends @TA Object> E o50(GenericMethods1<@TA ? super Number> e) { return null; }
public <@TA M extends @TB List & @TC Cloneable> E o60(@TA E e) { return null; }
// ctors
public GenericMethods1(List<? extends List> e, int i) throws Error, RuntimeException { }
public <E extends List & Cloneable> GenericMethods1(char c, E e, byte ... b) { }
@TC public <M extends Error, N extends RuntimeException> GenericMethods1(List<@TC E> e) throws @TA M, @TB @TC N { }
public <@TA M extends @TB List & @TC Cloneable> GenericMethods1(@TA E e, @TB M m) throws @TA Exception { }
public <@TA M extends @TB List & @TC Cloneable> GenericMethods1(@TA E e, @TB M m, @TC byte ... b) throws Exception { }
}
// test default ctor
public static class GenericCtors1<T> {
}
}

View file

@ -0,0 +1,507 @@
/*
* Copyright (c) 2018, 2022, 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 8058202 8212081 8224012
* @summary Test java.lang.Object methods on AnnotatedType objects.
*/
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.regex.*;
/**
* Test toString, equals, and hashCode on various AnnotatedType objects.
*/
public class TestObjectMethods {
private static int errors = 0;
/*
* There are various subtypes of AnnotatedType implementations:
*
* AnnotatedType
* AnnotatedArrayType
* AnnotatedParameterizedType
* AnnotatedTypeVariable
* AnnotatedWildcardType
*
* The implementations of each these implementations are
* examined. Wildcards don't appear as top-level types and need to
* be extracted from bounds.
*
* AnnotatedTypes with and without annotations are examined as
* well.
*/
public static void main(String... args) {
Class<?>[] testClasses = {TypeHost.class, AnnotatedTypeHost.class};
for (Class<?> clazz : testClasses) {
testEqualsReflexivity(clazz);
testEquals(clazz);
}
testToString(TypeHost.class);
testToString(AnnotatedTypeHost.class);
testAnnotationsMatterForEquals(TypeHost.class, AnnotatedTypeHost.class);
testGetAnnotations(TypeHost.class, false);
testGetAnnotations(AnnotatedTypeHost.class, true);
testWildcards();
testFbounds();
if (errors > 0) {
throw new RuntimeException(errors + " errors");
}
}
/*
* For non-array types, verify toString version of the annotated
* type ends with the same string as the generic type.
*/
static void testToString(Class<?> clazz) {
System.err.println("Testing toString on methods of class " + clazz.getName());
Method[] methods = clazz.getDeclaredMethods();
for (Method m : methods) {
// Expected information about the type annotations stored
// in a *declaration* annotation.
AnnotTypeInfo annotTypeInfo = m.getAnnotation(AnnotTypeInfo.class);
int expectedAnnotCount = annotTypeInfo.count();
Relation relation = annotTypeInfo.relation();
AnnotatedType annotType = m.getAnnotatedReturnType();
String annotTypeString = annotType.toString();
Type type = m.getGenericReturnType();
String typeString = (type instanceof Class) ?
type.getTypeName() :
type.toString();
boolean isArray = annotType instanceof AnnotatedArrayType;
boolean isVoid = "void".equals(typeString);
boolean valid;
switch(relation) {
case EQUAL:
valid = annotTypeString.equals(typeString);
break;
case POSTFIX:
valid = annotTypeString.endsWith(typeString) &&
!annotTypeString.startsWith(typeString);
break;
case STRIPPED:
String stripped = annotationRegex.matcher(annotTypeString).replaceAll("");
valid = typeString.replace(" ", "").equals(stripped.replace(" ", ""));
break;
case ARRAY:
// Find final non-array component type and gets its name.
typeString = null;
AnnotatedType componentType = annotType;
while (componentType instanceof AnnotatedArrayType) {
AnnotatedArrayType annotatedArrayType = (AnnotatedArrayType) componentType;
componentType = annotatedArrayType.getAnnotatedGenericComponentType();
}
String componentName = componentType.getType().getTypeName();
valid = annotTypeString.contains(componentName);
break;
case OTHER:
// No additional checks
valid = true;
break;
default:
throw new AssertionError("Shouldn't be reached");
}
// Verify number of type annotations matches expected value
Matcher matcher = annotationRegex.matcher(annotTypeString);
if (expectedAnnotCount > 0) {
int i = expectedAnnotCount;
int annotCount = 0;
while (i > 0) {
boolean found = matcher.find();
if (found) {
i--;
annotCount++;
} else {
errors++;
System.err.println("\tExpected annotation not found: " + annotTypeString);
}
}
}
boolean found = matcher.find();
if (found) {
errors++;
System.err.println("\tAnnotation found unexpectedly: " + annotTypeString);
}
if (!valid) {
errors++;
System.err.println(typeString + "\n" + annotTypeString +
"\n " + valid +
"\n\n");
}
}
}
private static final Pattern annotationRegex = Pattern.compile("@TestObjectMethods\\.AnnotType\\((\\p{Digit})+\\)");
static void testGetAnnotations(Class<?> clazz, boolean annotationsExpectedOnMethods) {
System.err.println("Testing getAnnotations on methods of class " + clazz.getName());
Method[] methods = clazz.getDeclaredMethods();
for (Method m : methods) {
Type type = m.getGenericReturnType();
AnnotatedType annotType = m.getAnnotatedReturnType();
Annotation[] annotations = annotType.getAnnotations();
boolean isVoid = "void".equals(type.toString());
if (annotationsExpectedOnMethods && !isVoid) {
if (annotations.length == 0 ) {
errors++;
System.err.println("Expected annotations missing on " + annotType);
}
} else {
if (annotations.length > 0 ) {
errors++;
System.err.println("Unexpected annotations present on " + annotType);
}
}
}
}
static void testEqualsReflexivity(Class<?> clazz) {
System.err.println("Testing reflexivity of equals on methods of class " + clazz.getName());
Method[] methods = clazz.getDeclaredMethods();
for (Method m : methods) {
checkTypesForEquality(m.getAnnotatedReturnType(),
m.getAnnotatedReturnType(),
true);
}
}
private static void checkTypesForEquality(AnnotatedType annotType1,
AnnotatedType annotType2,
boolean expected) {
boolean comparison = annotType1.equals(annotType2);
if (comparison) {
int hash1 = annotType1.hashCode();
int hash2 = annotType2.hashCode();
if (hash1 != hash2) {
errors++;
System.err.format("Equal AnnotatedTypes with unequal hash codes: %n%s%n%s%n",
annotType1.toString(), annotType2.toString());
}
}
if (comparison != expected) {
errors++;
System.err.println(annotType1);
System.err.println(expected ? " is not equal to " : " is equal to ");
System.err.println(annotType2);
System.err.println();
}
}
/*
* For each of the type host classes, the return type of a method
* should only equal the return type of that method.
*/
static void testEquals(Class<?> clazz) {
Method[] methods = clazz.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
for (int j = 0; j < methods.length; j++) {
if (i == j)
continue;
else {
checkTypesForEquality(methods[i].getAnnotatedReturnType(),
methods[j].getAnnotatedReturnType(),
false);
}
}
}
}
/**
* Roughly, compare the return types of corresponding methods on
* TypeHost and AnnotatedtypeHost and verify the AnnotatedType
* objects are *not* equal even if their underlying generic types
* are.
*/
static void testAnnotationsMatterForEquals(Class<?> clazz1, Class<?> clazz2) {
System.err.println("Testing that presence/absence of annotations matters for equals comparison.");
String methodName = null;
for (Method method : clazz1.getDeclaredMethods()) {
if ("void".equals(method.getReturnType().toString())) {
continue;
}
methodName = method.getName();
try {
checkTypesForEquality(method.getAnnotatedReturnType(),
clazz2.getDeclaredMethod(methodName).getAnnotatedReturnType(),
false);
} catch (Exception e) {
errors++;
System.err.println("Method " + methodName + " not found.");
}
}
}
static void testWildcards() {
System.err.println("Testing wildcards");
// public @AnnotType(10) Set<? extends Number> fooNumberSet() {return null;}
// public @AnnotType(11) Set<@AnnotType(13) ? extends Number> fooNumberSet2() {return null;}
AnnotatedWildcardType awt1 = extractWildcard("fooNumberSet");
AnnotatedWildcardType awt2 = extractWildcard("fooNumberSet2");
if (!awt1.equals(extractWildcard("fooNumberSet")) ||
!awt2.equals(extractWildcard("fooNumberSet2"))) {
errors++;
System.err.println("Bad equality comparison on wildcards.");
}
checkTypesForEquality(awt1, awt2, false);
if (awt2.getAnnotations().length == 0) {
errors++;
System.err.println("Expected annotations not found.");
}
}
private static AnnotatedWildcardType extractWildcard(String methodName) {
try {
return (AnnotatedWildcardType)
(((AnnotatedParameterizedType)(AnnotatedTypeHost.class.getMethod(methodName).
getAnnotatedReturnType())).
getAnnotatedActualTypeArguments()[0] );
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static void testFbounds() {
// Make sure equals and hashCode work fine for a type
// involving an F-bound, in particular Comparable<E> in
// java.lang.Enum:
//
// class Enum<E extends Enum<E>>
// implements Constable, Comparable<E>, Serializable
AnnotatedType[] types = Enum.class.getAnnotatedInterfaces();
for (int i = 0; i < types.length; i ++) {
for (int j = 0; j < types.length; j ++) {
checkTypesForEquality(types[i], types[j], i == j);
}
}
}
// The TypeHost and AnnotatedTypeHost classes declare methods with
// the same name and signatures but with the AnnotatedTypeHost
// methods having annotations on their return type, where
// possible.
static class TypeHost<E, F extends Number> {
@AnnotTypeInfo
public void fooVoid() {return;}
@AnnotTypeInfo
public int foo() {return 0;}
@AnnotTypeInfo
public String fooString() {return null;}
@AnnotTypeInfo
public int[] fooIntArray() {return null;}
@AnnotTypeInfo
public String[] fooStringArray() {return null;}
@AnnotTypeInfo
public String [][] fooStringArrayArray() {return null;}
@AnnotTypeInfo
public Set<String> fooSetString() {return null;}
@AnnotTypeInfo
public Set<Number> fooSetNumber() {return null;}
@AnnotTypeInfo
public E fooE() {return null;}
@AnnotTypeInfo
public F fooF() {return null;}
@AnnotTypeInfo
public <G> G fooG() {return null;}
@AnnotTypeInfo
public Set<? extends Number> fooNumberSet() {return null;}
@AnnotTypeInfo
public Set<? extends Integer> fooNumberSet2() {return null;}
@AnnotTypeInfo
public Set<? extends Long> fooNumberSet3() {return null;}
@AnnotTypeInfo
public Set<?> fooObjectSet() {return null;}
@AnnotTypeInfo
public List<? extends Object> fooObjectList() {return null;}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
static @interface AnnotType {
int value() default 0;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
static @interface AnnotTypeInfo {
/**
* Expected number of @AnnotType
*/
int count() default 0;
/**
* Relation to genericString output.
*/
Relation relation() default Relation.EQUAL;
}
/**
* Expected relationship of toString output of AnnotatedType to
* toGenericString output of underlying type.
*/
static private enum Relation {
EQUAL,
/**
* The toGenericString output is a postfix of the
* AnnotatedType output; a leading annotation is expected.
*/
POSTFIX,
/**
* If the annotations are stripped from the AnnotatedType
* output and whitespace adjusted accordingly, it should equal
* the toGenericString output.
*/
STRIPPED,
/**
* The output of AnnotatedType for arrays would require more
* extensive transformation to map to toGenericString output.
*/
ARRAY,
/**
* Some other, harder to characterize, relationship. Currently
* used for a wildcard where Object in "extends Object" is
* annotated; the "extends Object" is elided in toGenericString.
*/
OTHER;
}
static class AnnotatedTypeHost<E, F extends Number> {
@AnnotTypeInfo
public /*@AnnotType(0)*/ void fooVoid() {return;} // Illegal to annotate void
@AnnotTypeInfo(count =1, relation = Relation.POSTFIX)
@AnnotType(1)
public int foo() {return 0;}
@AnnotTypeInfo(count = 1, relation = Relation.POSTFIX)
@AnnotType(2)
public String fooString() {return null;}
@AnnotTypeInfo(count = 1, relation = Relation.ARRAY)
public int @AnnotType(3) [] fooIntArray() {return null;}
@AnnotTypeInfo(count = 1, relation = Relation.ARRAY)
public String @AnnotType(4) [] fooStringArray() {return null;}
@AnnotTypeInfo(count = 3, relation = Relation.ARRAY)
@AnnotType(5)
public String @AnnotType(0) [] @AnnotType(1) [] fooStringArrayArray() {return null;}
@AnnotTypeInfo(count = 1, relation = Relation.POSTFIX)
@AnnotType(6)
public Set<String> fooSetString() {return null;}
@AnnotTypeInfo(count = 2, relation = Relation.STRIPPED)
@AnnotType(7)
public Set<@AnnotType(8) Number> fooSetNumber() {return null;}
@AnnotTypeInfo(count = 1, relation = Relation.POSTFIX)
@AnnotType(9)
public E fooE() {return null;}
@AnnotTypeInfo(count = 1, relation = Relation.POSTFIX)
@AnnotType(10)
public F fooF() {return null;}
@AnnotTypeInfo(count = 1, relation = Relation.POSTFIX)
@AnnotType(11)
public <G> G fooG() {return null;}
@AnnotTypeInfo(count = 1, relation = Relation.POSTFIX)
@AnnotType(12)
public Set<? extends Number> fooNumberSet() {return null;}
@AnnotTypeInfo(count = 2, relation = Relation.STRIPPED)
@AnnotType(13)
public Set<@AnnotType(14) ? extends Number> fooNumberSet2() {return null;}
@AnnotTypeInfo(count = 2, relation = Relation.STRIPPED)
@AnnotType(15)
public Set< ? extends @AnnotType(16) Long> fooNumberSet3() {return null;}
@AnnotTypeInfo(count = 2, relation = Relation.STRIPPED)
@AnnotType(16)
public Set<@AnnotType(17) ?> fooObjectSet() {return null;}
@AnnotTypeInfo(count = 2, relation = Relation.OTHER)
@AnnotType(18)
public List<? extends @AnnotType(19) Object> fooObjectList() {return null;}
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2020, 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 8202471
* @summary A nested class's owner can be type annotated if used as a receiver type
*/
import java.lang.annotation.Target;
import java.lang.annotation.*;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
public class TestReceiverTypeOwner<T> {
public static void main(String[] args) throws NoSuchMethodException {
Method method = TestReceiverTypeOwner.Inner.class.getDeclaredMethod("m");
AnnotatedType receiverType = method.getAnnotatedReceiverType();
AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) receiverType;
AnnotatedType owner = parameterizedType.getAnnotatedOwnerType();
Annotation[] annotations = owner.getAnnotations();
if (annotations.length != 1 || !(annotations[0] instanceof TypeAnnotation)) {
throw new AssertionError();
}
}
class Inner {
void m(@TypeAnnotation TestReceiverTypeOwner<T>.Inner this) { }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface TypeAnnotation { }
}

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2021, 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 8259224
* @summary A receiver type's owner type is of the correct type for nested classes.
*/
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
public class TestReceiverTypeOwnerType<T> {
public static void main(String[] args) throws Exception {
AnnotatedType nested = Class.forName(TestReceiverTypeOwnerType.class.getTypeName() + "$Nested").getMethod("method").getAnnotatedReceiverType();
if (!(nested instanceof AnnotatedParameterizedType)) {
throw new AssertionError();
} else if (!(nested.getAnnotatedOwnerType() instanceof AnnotatedParameterizedType)) {
throw new AssertionError();
}
AnnotatedType inner = Inner.class.getMethod("method").getAnnotatedReceiverType();
if (inner instanceof AnnotatedParameterizedType) {
throw new AssertionError();
} else if (inner.getAnnotatedOwnerType() instanceof AnnotatedParameterizedType) {
throw new AssertionError();
}
AnnotatedType nestedInner = GenericInner.class.getMethod("method").getAnnotatedReceiverType();
if (!(nestedInner instanceof AnnotatedParameterizedType)) {
throw new AssertionError();
} else if (nestedInner.getAnnotatedOwnerType() instanceof AnnotatedParameterizedType) {
throw new AssertionError();
}
}
public class Nested {
public void method(TestReceiverTypeOwnerType<T>.Nested this) { }
}
public static class Inner {
public void method(TestReceiverTypeOwnerType.Inner this) { }
}
public static class GenericInner<S> {
public void method(TestReceiverTypeOwnerType.GenericInner<S> this) { }
}
}

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2020, 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 8202471
* @summary A constructor's parameterized receiver type's type variables can be type annotated
*/
import java.lang.annotation.Target;
import java.lang.annotation.*;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Constructor;
public class TestReceiverTypeParameterizedConstructor<T> {
public static void main(String[] args) throws NoSuchMethodException {
doAssert(TestReceiverTypeParameterizedConstructor.Inner.class);
doAssert(TestReceiverTypeParameterizedConstructor.Inner.Inner2.class);
}
private static void doAssert(Class<?> c) throws NoSuchMethodException {
Constructor<?> constructor = c.getDeclaredConstructor(c.getDeclaringClass());
AnnotatedType receiverType = constructor.getAnnotatedReceiverType();
AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) receiverType;
int count = 0;
do {
AnnotatedType[] arguments = parameterizedType.getAnnotatedActualTypeArguments();
Annotation[] annotations = arguments[0].getAnnotations();
if (annotations.length != 1
|| !(annotations[0] instanceof TypeAnnotation)
|| ((TypeAnnotation) annotations[0]).value() != count++) {
throw new AssertionError();
}
parameterizedType = (AnnotatedParameterizedType) parameterizedType.getAnnotatedOwnerType();
} while (parameterizedType != null);
}
class Inner<S> {
Inner(TestReceiverTypeParameterizedConstructor<@TypeAnnotation(0) T> TestReceiverTypeParameterizedConstructor.this) { }
class Inner2 {
Inner2(TestReceiverTypeParameterizedConstructor<@TypeAnnotation(1) T>.Inner<@TypeAnnotation(0) S> TestReceiverTypeParameterizedConstructor.Inner.this) { }
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface TypeAnnotation {
int value();
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2020, 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 8202471
* @summary A method's parameterized receiver type's type variables can be type annotated
*/
import java.lang.annotation.Target;
import java.lang.annotation.*;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
public class TestReceiverTypeParameterizedMethod<T> {
public static void main(String[] args) throws NoSuchMethodException {
doAssert(TestReceiverTypeParameterizedMethod.class);
doAssert(TestReceiverTypeParameterizedMethod.Inner.class);
}
private static void doAssert(Class<?> c) throws NoSuchMethodException {
Method method = c.getDeclaredMethod("m");
AnnotatedType receiverType = method.getAnnotatedReceiverType();
AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) receiverType;
int count = 0;
do {
AnnotatedType[] arguments = parameterizedType.getAnnotatedActualTypeArguments();
Annotation[] annotations = arguments[0].getAnnotations();
if (annotations.length != 1
|| !(annotations[0] instanceof TypeAnnotation)
|| ((TypeAnnotation) annotations[0]).value() != count++) {
throw new AssertionError();
}
parameterizedType = (AnnotatedParameterizedType) parameterizedType.getAnnotatedOwnerType();
} while (parameterizedType != null);
}
void m(TestReceiverTypeParameterizedMethod<@TypeAnnotation(0) T> this) { }
class Inner<S> {
void m(TestReceiverTypeParameterizedMethod<@TypeAnnotation(1) T>.Inner<@TypeAnnotation(0) S> this) { }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface TypeAnnotation {
int value();
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2020, 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 8202473
* @summary Annotations on type variables with multiple bounds should be placed on their respective bound
* @compile TypeVariableBoundParameterIndex.java
* @run main TypeVariableBoundParameterIndex
*/
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.TypeVariable;
import java.util.concurrent.Callable;
/*
* A class might have multiple bounds as parameterized types with type annotations on these bounds.
* This test assures that these bound annotations are resolved correctly.
*/
public class TypeVariableBoundParameterIndex {
public static void main(String[] args) throws Exception {
TypeVariable<?>[] variables = Sample.class.getTypeParameters();
for (int i = 0; i < 2; i++) {
TypeVariable<?> variable = variables[i];
AnnotatedType[] bounds = variable.getAnnotatedBounds();
AnnotatedType bound = bounds[0];
AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) bound;
AnnotatedType[] actualTypeArguments = parameterizedType.getAnnotatedActualTypeArguments();
Annotation[] annotations = actualTypeArguments[0].getAnnotations();
if (annotations.length != 1 || annotations[0].annotationType() != TypeAnnotation.class) {
throw new AssertionError();
}
}
TypeVariable<?> variable = variables[2];
AnnotatedType[] bounds = variable.getAnnotatedBounds();
AnnotatedType bound = bounds[0];
AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) bound;
AnnotatedType[] actualTypeArguments = parameterizedType.getAnnotatedActualTypeArguments();
Annotation[] annotations = actualTypeArguments[0].getAnnotations();
if (annotations.length != 0) {
throw new AssertionError();
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface TypeAnnotation { }
static class Sample<T extends Callable<@TypeAnnotation ?>, S extends Callable<@TypeAnnotation ?>, U extends Callable<?>> { }
}