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:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
77
test/jdk/java/lang/reflect/Generics/HashCodeTest.java
Normal file
77
test/jdk/java/lang/reflect/Generics/HashCodeTest.java
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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 5097856
|
||||
* @summary Computing hashCode of objects modeling generics shouldn't blow stack
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class HashCodeTest {
|
||||
|
||||
// Mutually recursive interface types
|
||||
interface Edge<N extends Node<? extends Edge<N>>> {
|
||||
void setEndNode(N n);
|
||||
}
|
||||
interface Node<E extends Edge<? extends Node<E>>> {
|
||||
E getOutEdge();
|
||||
}
|
||||
|
||||
public static void main(String argv[]) {
|
||||
List<Class<?>> classes = new ArrayList<Class<?>>();
|
||||
Set<TypeVariable> typeVariables = new HashSet<TypeVariable>();
|
||||
|
||||
classes.add(java.lang.Class.class);// Simple case
|
||||
classes.add(java.util.Map.class);
|
||||
classes.add(java.lang.Enum.class); // Contains f-bound
|
||||
classes.add(Edge.class);
|
||||
classes.add(Node.class);
|
||||
|
||||
for(Class<?> clazz: classes) {
|
||||
System.out.println(clazz);
|
||||
|
||||
for (TypeVariable<?> tv : clazz.getTypeParameters()) {
|
||||
int hc = tv.hashCode();
|
||||
typeVariables.add(tv);
|
||||
System.out.printf("\t%s 0x%x (%d)%n", tv.getName(), hc, hc);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop over classes again, making sure all type variables are
|
||||
// already present
|
||||
int count = 0;
|
||||
for(Class<?> clazz: classes) {
|
||||
for (TypeVariable<?> tv : clazz.getTypeParameters()) {
|
||||
if (!typeVariables.remove(tv))
|
||||
throw new RuntimeException("Type variable " + tv + " not found.");
|
||||
}
|
||||
}
|
||||
|
||||
if (typeVariables.size() != 0 )
|
||||
throw new RuntimeException("Unexpected number of type variables.");
|
||||
|
||||
}
|
||||
}
|
||||
224
test/jdk/java/lang/reflect/Generics/MalformedSignatureTest.java
Normal file
224
test/jdk/java/lang/reflect/Generics/MalformedSignatureTest.java
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* 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 6832374 7052898 8350704
|
||||
* @summary Test behaviors with malformed signature strings in Signature attribute.
|
||||
* @library /test/lib
|
||||
* @run junit MalformedSignatureTest
|
||||
*/
|
||||
|
||||
import java.lang.classfile.*;
|
||||
import java.lang.classfile.attribute.RecordAttribute;
|
||||
import java.lang.classfile.attribute.RecordComponentInfo;
|
||||
import java.lang.classfile.attribute.SignatureAttribute;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.reflect.GenericSignatureFormatError;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.test.lib.ByteCodeLoader;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static java.lang.constant.ConstantDescs.MTD_void;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class MalformedSignatureTest {
|
||||
|
||||
private static final String BASIC_BAD_SIGNATURE_TEXT = "i_aM_NoT_A_Signature";
|
||||
static Class<?> sampleClass, sampleRecord;
|
||||
|
||||
@BeforeAll
|
||||
static void setup() throws Exception {
|
||||
var compiledDir = Path.of(System.getProperty("test.classes"));
|
||||
var cf = ClassFile.of();
|
||||
|
||||
// Transform that installs malformed signature strings to classes,
|
||||
// fields, methods, and record components.
|
||||
var badSignatureTransform = new ClassTransform() {
|
||||
private SignatureAttribute badSignature;
|
||||
|
||||
@Override
|
||||
public void atStart(ClassBuilder builder) {
|
||||
badSignature = SignatureAttribute.of(builder.constantPool().utf8Entry(BASIC_BAD_SIGNATURE_TEXT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ClassBuilder builder, ClassElement element) {
|
||||
switch (element) {
|
||||
case SignatureAttribute _ -> {} // dropping
|
||||
case FieldModel f -> builder
|
||||
.transformField(f, FieldTransform.dropping(SignatureAttribute.class::isInstance)
|
||||
.andThen(FieldTransform.endHandler(fb -> fb.with(badSignature))));
|
||||
case MethodModel m -> builder
|
||||
.transformMethod(m, MethodTransform.dropping(SignatureAttribute.class::isInstance)
|
||||
.andThen(MethodTransform.endHandler(fb -> fb.with(badSignature))));
|
||||
case RecordAttribute rec -> builder.with(RecordAttribute.of(rec.components().stream().map(comp ->
|
||||
RecordComponentInfo.of(comp.name(), comp.descriptor(), Stream.concat(
|
||||
Stream.of(badSignature), comp.attributes().stream()
|
||||
.filter(Predicate.not(SignatureAttribute.class::isInstance)))
|
||||
.toList()))
|
||||
.toList()));
|
||||
default -> builder.with(element);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void atEnd(ClassBuilder builder) {
|
||||
builder.with(badSignature);
|
||||
}
|
||||
};
|
||||
|
||||
var plainBytes = cf.transformClass(cf.parse(compiledDir.resolve("SampleClass.class")), badSignatureTransform);
|
||||
sampleClass = ByteCodeLoader.load("SampleClass", plainBytes);
|
||||
var recordBytes = cf.transformClass(cf.parse(compiledDir.resolve("SampleRecord.class")), badSignatureTransform);
|
||||
sampleRecord = ByteCodeLoader.load("SampleRecord", recordBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the reflective generic inspection of a malformed Class throws
|
||||
* GenericSignatureFormatError while the non-generic inspection is fine.
|
||||
*/
|
||||
@Test
|
||||
void testBasicClass() {
|
||||
assertEquals(ArrayList.class, sampleClass.getSuperclass());
|
||||
assertArrayEquals(new Class<?>[] {Predicate.class}, sampleClass.getInterfaces());
|
||||
var ex = assertThrows(GenericSignatureFormatError.class, sampleClass::getGenericSuperclass);
|
||||
assertTrue(ex.getMessage().contains(BASIC_BAD_SIGNATURE_TEXT));
|
||||
ex = assertThrows(GenericSignatureFormatError.class, sampleClass::getGenericInterfaces);
|
||||
assertTrue(ex.getMessage().contains(BASIC_BAD_SIGNATURE_TEXT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the reflective generic inspection of a malformed Field throws
|
||||
* GenericSignatureFormatError while the non-generic inspection is fine.
|
||||
*/
|
||||
@Test
|
||||
void testBasicField() throws ReflectiveOperationException {
|
||||
var field = sampleClass.getDeclaredField("field");
|
||||
assertEquals(Optional.class, field.getType());
|
||||
var ex = assertThrows(GenericSignatureFormatError.class, field::getGenericType);
|
||||
assertTrue(ex.getMessage().contains(BASIC_BAD_SIGNATURE_TEXT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the reflective generic inspection of a malformed Constructor throws
|
||||
* GenericSignatureFormatError while the non-generic inspection is fine.
|
||||
*/
|
||||
@Test
|
||||
void testBasicConstructor() throws ReflectiveOperationException {
|
||||
var constructor = sampleClass.getDeclaredConstructors()[0];
|
||||
assertArrayEquals(new Class<?>[] {Optional.class}, constructor.getParameterTypes());
|
||||
assertArrayEquals(new Class<?>[] {RuntimeException.class}, constructor.getExceptionTypes());
|
||||
var ex = assertThrows(GenericSignatureFormatError.class, constructor::getGenericParameterTypes);
|
||||
assertTrue(ex.getMessage().contains(BASIC_BAD_SIGNATURE_TEXT));
|
||||
ex = assertThrows(GenericSignatureFormatError.class, constructor::getGenericExceptionTypes);
|
||||
assertTrue(ex.getMessage().contains(BASIC_BAD_SIGNATURE_TEXT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the reflective generic inspection of a malformed Method throws
|
||||
* GenericSignatureFormatError while the non-generic inspection is fine.
|
||||
*/
|
||||
@Test
|
||||
void testBasicMethod() throws ReflectiveOperationException {
|
||||
var method = sampleClass.getDeclaredMethods()[0];
|
||||
assertEquals(Optional.class, method.getReturnType());
|
||||
assertArrayEquals(new Class<?>[] {Optional.class}, method.getParameterTypes());
|
||||
assertArrayEquals(new Class<?>[] {RuntimeException.class}, method.getExceptionTypes());
|
||||
var ex = assertThrows(GenericSignatureFormatError.class, method::getGenericReturnType);
|
||||
assertTrue(ex.getMessage().contains(BASIC_BAD_SIGNATURE_TEXT));
|
||||
ex = assertThrows(GenericSignatureFormatError.class, method::getGenericParameterTypes);
|
||||
assertTrue(ex.getMessage().contains(BASIC_BAD_SIGNATURE_TEXT));
|
||||
ex = assertThrows(GenericSignatureFormatError.class, method::getGenericExceptionTypes);
|
||||
assertTrue(ex.getMessage().contains(BASIC_BAD_SIGNATURE_TEXT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the reflective generic inspection of a malformed RecordComponent throws
|
||||
* GenericSignatureFormatError while the non-generic inspection is fine.
|
||||
*/
|
||||
@Test
|
||||
void testBasicRecordComponent() {
|
||||
var rcs = sampleRecord.getRecordComponents();
|
||||
assertNotNull(rcs);
|
||||
assertEquals(1, rcs.length);
|
||||
var rc = rcs[0];
|
||||
assertNotNull(rc);
|
||||
|
||||
assertEquals(Optional.class, rc.getType());
|
||||
assertEquals(BASIC_BAD_SIGNATURE_TEXT, rc.getGenericSignature());
|
||||
var ex = assertThrows(GenericSignatureFormatError.class, rc::getGenericType);
|
||||
assertTrue(ex.getMessage().contains(BASIC_BAD_SIGNATURE_TEXT));
|
||||
}
|
||||
|
||||
static String[] badMethodSignatures() {
|
||||
return new String[] {
|
||||
// Missing ":" after first type bound
|
||||
"<T:Lfoo/tools/nsc/symtab/Names;Lfoo/tools/nsc/symtab/Symbols;",
|
||||
|
||||
// Arrays improperly indicated for exception information
|
||||
"<E:Ljava/lang/Exception;>(TE;[Ljava/lang/RuntimeException;)V^[TE;",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that particular strings are invalid as method signature strings.
|
||||
*/
|
||||
@MethodSource("badMethodSignatures")
|
||||
@ParameterizedTest
|
||||
void testSignatureForMethod(String badSig) throws Throwable {
|
||||
var className = "BadSignature";
|
||||
var bytes = ClassFile.of().build(ClassDesc.of(className), clb ->
|
||||
clb.withMethod("test", MTD_void, 0, mb -> mb
|
||||
.withCode(CodeBuilder::return_)
|
||||
.with(SignatureAttribute.of(clb.constantPool().utf8Entry(badSig)))));
|
||||
|
||||
var cl = ByteCodeLoader.load(className, bytes);
|
||||
var method = cl.getDeclaredMethod("test");
|
||||
var ex = assertThrows(GenericSignatureFormatError.class, method::getGenericParameterTypes);
|
||||
//assertTrue(ex.getMessage().contains(badSig), "Missing bad signature in error message");
|
||||
}
|
||||
}
|
||||
|
||||
// Sample classes shared with TypeNotPresentInSignatureTest
|
||||
abstract class SampleClass extends ArrayList<RuntimeException> implements Predicate<RuntimeException> { // class
|
||||
Optional<RuntimeException> field; // field
|
||||
|
||||
<T extends RuntimeException> SampleClass(Optional<RuntimeException> param) throws T {
|
||||
} // constructor
|
||||
|
||||
<T extends RuntimeException> Optional<RuntimeException> method(Optional<RuntimeException> param) throws T {
|
||||
return null;
|
||||
} // method
|
||||
}
|
||||
|
||||
record SampleRecord(Optional<RuntimeException> component) {
|
||||
}
|
||||
132
test/jdk/java/lang/reflect/Generics/Probe.java
Normal file
132
test/jdk/java/lang/reflect/Generics/Probe.java
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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 5003916 6704655 6873951 6476261 8004928
|
||||
* @summary Testing parsing of signatures attributes of nested classes
|
||||
*/
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.lang.annotation.*;
|
||||
import java.util.*;
|
||||
import static java.util.Arrays.*;
|
||||
|
||||
@Classes({"java.util.concurrent.FutureTask",
|
||||
"java.util.concurrent.ConcurrentHashMap$EntryIterator",
|
||||
"java.util.concurrent.ConcurrentHashMap$KeyIterator",
|
||||
"java.util.concurrent.ConcurrentHashMap$ValueIterator",
|
||||
"java.util.AbstractList$ListItr",
|
||||
"java.util.EnumMap$EntryIterator",
|
||||
"java.util.EnumMap$KeyIterator",
|
||||
"java.util.EnumMap$ValueIterator",
|
||||
"java.util.IdentityHashMap$EntryIterator",
|
||||
"java.util.IdentityHashMap$KeyIterator",
|
||||
"java.util.IdentityHashMap$ValueIterator",
|
||||
"java.util.WeakHashMap$EntryIterator",
|
||||
"java.util.WeakHashMap$KeyIterator",
|
||||
"java.util.WeakHashMap$ValueIterator",
|
||||
"java.util.HashMap$EntryIterator",
|
||||
"java.util.HashMap$KeyIterator",
|
||||
"java.util.HashMap$ValueIterator",
|
||||
"java.util.LinkedHashMap$LinkedEntryIterator",
|
||||
"java.util.LinkedHashMap$LinkedKeyIterator",
|
||||
"java.util.LinkedHashMap$LinkedValueIterator"})
|
||||
public class Probe {
|
||||
public static void main (String... args) throws Throwable {
|
||||
Classes classesAnnotation = (Probe.class).getAnnotation(Classes.class);
|
||||
List<String> names = new ArrayList<>(asList(classesAnnotation.value()));
|
||||
|
||||
int errs = 0;
|
||||
for(String name: names) {
|
||||
System.out.println("\nCLASS " + name);
|
||||
Class c = Class.forName(name, false, null);
|
||||
errs += probe(c);
|
||||
System.out.println(errs == 0 ? " ok" : " ERRORS:" + errs);
|
||||
}
|
||||
|
||||
if (errs > 0 )
|
||||
throw new RuntimeException("Errors during probing.");
|
||||
}
|
||||
|
||||
static int probe (Class c) {
|
||||
int errs = 0;
|
||||
|
||||
try {
|
||||
c.getTypeParameters();
|
||||
c.getGenericSuperclass();
|
||||
c.getGenericInterfaces();
|
||||
} catch (Throwable t) {
|
||||
errs++;
|
||||
System.err.println(t);
|
||||
}
|
||||
|
||||
Field[] fields = c.getDeclaredFields();
|
||||
if (fields != null)
|
||||
for(Field field: fields) {
|
||||
try {
|
||||
field.getGenericType();
|
||||
} catch (Throwable t) {
|
||||
errs++;
|
||||
System.err.println("FIELD " + field);
|
||||
System.err.println(t);
|
||||
}
|
||||
}
|
||||
|
||||
Method[] methods = c.getDeclaredMethods();
|
||||
if (methods != null)
|
||||
for(Method method: methods) {
|
||||
try {
|
||||
method.getTypeParameters();
|
||||
method.getGenericReturnType();
|
||||
method.getGenericParameterTypes();
|
||||
method.getGenericExceptionTypes();
|
||||
} catch (Throwable t) {
|
||||
errs++;
|
||||
System.err.println("METHOD " + method);
|
||||
System.err.println(t);
|
||||
}
|
||||
}
|
||||
|
||||
Constructor[] ctors = c.getDeclaredConstructors();
|
||||
if (ctors != null)
|
||||
for(Constructor ctor: ctors) {
|
||||
try {
|
||||
ctor.getTypeParameters();
|
||||
ctor.getGenericParameterTypes();
|
||||
ctor.getGenericExceptionTypes();
|
||||
} catch (Throwable t) {
|
||||
errs++;
|
||||
System.err.println("CONSTRUCTOR " + ctor);
|
||||
System.err.println(t);
|
||||
}
|
||||
}
|
||||
|
||||
return errs;
|
||||
}
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Classes {
|
||||
String [] value(); // list of classes to probe
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 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 8372258
|
||||
* @summary Test if a copy of the internal state is provided
|
||||
* @run junit ProtectInnerStateOfTypeVariableImplTest
|
||||
*/
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
final class ProtectInnerStateOfTypeVariableImplTest {
|
||||
|
||||
static final class Foo {
|
||||
public <X> Foo() {
|
||||
}
|
||||
|
||||
<X> X x() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMethod() throws NoSuchMethodException {
|
||||
Method method = Foo.class.getDeclaredMethod("x");
|
||||
TypeVariable<Method> tv = method.getTypeParameters()[0];
|
||||
|
||||
Method gd = tv.getGenericDeclaration();
|
||||
Method gd2 = tv.getGenericDeclaration();
|
||||
assertNotSame(gd, gd2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConstructor() throws NoSuchMethodException {
|
||||
Constructor<?> ctor = Foo.class.getConstructor();
|
||||
TypeVariable<? extends Constructor<?>> tv = ctor.getTypeParameters()[0];
|
||||
|
||||
Constructor<?> gd = tv.getGenericDeclaration();
|
||||
Constructor<?> gd2 = tv.getGenericDeclaration();
|
||||
assertNotSame(gd, gd2);
|
||||
}
|
||||
|
||||
}
|
||||
50
test/jdk/java/lang/reflect/Generics/SignatureTest.java
Normal file
50
test/jdk/java/lang/reflect/Generics/SignatureTest.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 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 6476261
|
||||
* @summary More testing of parsing of signatures attributes of nested classes
|
||||
*/
|
||||
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class SignatureTest<T> {
|
||||
class Inner1 {
|
||||
class Inner11 {
|
||||
}
|
||||
}
|
||||
|
||||
public void f(SignatureTest<String>.Inner1.Inner11 x) {}
|
||||
public void g(SignatureTest<String>.Inner1 x) {}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class clazz = SignatureTest.class;
|
||||
for (Method m : clazz.getDeclaredMethods()) {
|
||||
System.out.println();
|
||||
System.out.println(m.toString());
|
||||
System.out.println(m.toGenericString());
|
||||
System.out.println(m.getGenericParameterTypes());
|
||||
}
|
||||
}
|
||||
}
|
||||
93
test/jdk/java/lang/reflect/Generics/StringsAndBounds.java
Normal file
93
test/jdk/java/lang/reflect/Generics/StringsAndBounds.java
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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 5015676 4987888 4997464
|
||||
* @summary Testing upper bounds and availability of toString methods
|
||||
*/
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
class A<T> {
|
||||
class B<U> {}
|
||||
}
|
||||
|
||||
class Test<T> {
|
||||
static class Inner1<U> {
|
||||
void bar(U[] array1) { return;}
|
||||
}
|
||||
|
||||
class Inner2<V> {
|
||||
List<?> foo2(List<? extends V> t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static <S extends Object & Comparable<? super S> > S max(Collection<? extends S> coll) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<? extends T> foo(List<? super T> t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class StringsAndBounds {
|
||||
public void f(A<String>.B<Integer> x) {
|
||||
}
|
||||
|
||||
public <T> void g(T a) {return ;}
|
||||
|
||||
static void scanner(Class clazz) {
|
||||
System.out.println("\n\nScanning " + clazz.getName());
|
||||
|
||||
for(Class c: clazz.getDeclaredClasses()) {
|
||||
scanner(c);
|
||||
}
|
||||
|
||||
for(Method m: clazz.getDeclaredMethods()) {
|
||||
System.out.println("\nMethod:\t" + m.toString()); // Need toGenericString?
|
||||
System.out.println("\tReturn Type: " + m.getGenericReturnType().toString() );
|
||||
for(Type p: m.getGenericParameterTypes()) {
|
||||
if (p instanceof WildcardType) { // Check upper bounds
|
||||
Type[] upperBounds = ((WildcardType)p).getUpperBounds();
|
||||
if (upperBounds.length < 1 ||
|
||||
upperBounds[0] == null)
|
||||
throw new RuntimeException("Malformed upper bounds: " + p);
|
||||
|
||||
}
|
||||
|
||||
System.out.println("\tParameter: " + p.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] argv) throws Exception {
|
||||
scanner(StringsAndBounds.class);
|
||||
scanner(A.B.class);
|
||||
scanner(Test.class);
|
||||
}
|
||||
}
|
||||
340
test/jdk/java/lang/reflect/Generics/TestC1.java
Normal file
340
test/jdk/java/lang/reflect/Generics/TestC1.java
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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 4891872
|
||||
* @summary Some tests for the generic core reflection api.
|
||||
* @author Gilad Bracha
|
||||
* @compile TestC1.java
|
||||
* @run main/othervm -ea TestC1
|
||||
*/
|
||||
|
||||
|
||||
import java.lang.reflect.*;
|
||||
|
||||
|
||||
abstract class C1<T> {
|
||||
|
||||
public T ft;
|
||||
public C1<T> fc1t;
|
||||
public C1 fc1;
|
||||
|
||||
public C1(T t) {}
|
||||
|
||||
public abstract C1<T> mc1t(T t, C1<T> c1t, C1 c1);
|
||||
|
||||
public abstract C1 mc1();
|
||||
|
||||
public abstract T mt(T t);
|
||||
|
||||
}
|
||||
|
||||
public class TestC1 {
|
||||
|
||||
static Class<C1> cls = C1.class;
|
||||
static {
|
||||
TestC1.class.getClassLoader().setDefaultAssertionStatus(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
testSuperclass();
|
||||
testSuperInterfaces();
|
||||
testTypeParameters();
|
||||
testMethods();
|
||||
testConstructor();
|
||||
testFields();
|
||||
}
|
||||
|
||||
static void testSuperclass() {
|
||||
System.out.println("testing superclass");
|
||||
Type sc = cls.getGenericSuperclass();
|
||||
assert
|
||||
(sc == Object.class) :
|
||||
"The generic superclass of C1 should be Object";
|
||||
}
|
||||
|
||||
static void testSuperInterfaces() {
|
||||
System.out.println("testing superinterfaces");
|
||||
Type[] sis = cls.getGenericInterfaces();
|
||||
assert
|
||||
(sis.length == 0) :
|
||||
"C1 should have no generic superinterfaces";
|
||||
}
|
||||
|
||||
static void testTypeParameters() {
|
||||
System.out.println("testing type parameters");
|
||||
TypeVariable[] tvs = cls.getTypeParameters();
|
||||
assert
|
||||
tvs.length == 1 :
|
||||
"C1 should have one type parameter";
|
||||
TypeVariable tv = tvs[0];
|
||||
Type[] bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T should have one bound";
|
||||
assert
|
||||
bs[0] == Object.class :
|
||||
"The default bound of a type variable should be Object";
|
||||
}
|
||||
|
||||
static void testMethods() throws NoSuchMethodException {
|
||||
System.out.println("testing methods");
|
||||
Class[] params1 = new Class[3];
|
||||
params1[0] = Object.class;
|
||||
params1[1] = cls;
|
||||
params1[2] = cls;
|
||||
|
||||
Class[] params3 = new Class[1];
|
||||
params3[0] = Object.class;
|
||||
|
||||
Method mc1t = cls.getMethod("mc1t", params1);
|
||||
Method mc1 = cls.getMethod("mc1", new Class[0]);
|
||||
Method mt = cls.getMethod("mt", params3);
|
||||
|
||||
Type rt_mc1t = mc1t.getGenericReturnType();
|
||||
Type rt_mc1 = mc1.getGenericReturnType();
|
||||
Type rt_mt = mt.getGenericReturnType();
|
||||
|
||||
Type[] pt_mc1t = mc1t.getGenericParameterTypes();
|
||||
|
||||
assert
|
||||
pt_mc1t.length == 3 :
|
||||
"C1.mc1t has three parameters";
|
||||
Type p1_mc1t = pt_mc1t[0];
|
||||
assert p1_mc1t != null;
|
||||
assert
|
||||
p1_mc1t instanceof TypeVariable :
|
||||
"Generic type of the 1st parameter of mc1t(T) is a type variable";
|
||||
TypeVariable tv = (TypeVariable) p1_mc1t;
|
||||
|
||||
assert
|
||||
tv.getName().equals("T") :
|
||||
"Name of 1st type parameter of mc1t is T, not " + tv.getName();
|
||||
Type[] bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T should have one bound (mc1t)";
|
||||
assert
|
||||
bs[0] == Object.class :
|
||||
"The bound of T should be Object (mc1t)";
|
||||
|
||||
Type p2_mc1t = pt_mc1t[1];
|
||||
|
||||
assert
|
||||
p2_mc1t instanceof ParameterizedType :
|
||||
"The type of parameter 2 of mc1t is a parameterized type";
|
||||
ParameterizedType pt = (ParameterizedType) p2_mc1t;
|
||||
assert
|
||||
pt.getRawType() == cls :
|
||||
"Type of parameter 2 of mc1t is instantiation of C1";
|
||||
assert
|
||||
pt.getOwnerType() == null :
|
||||
"Type of parameter 2 of mc1t is has null owner";
|
||||
|
||||
Type[] tas = pt.getActualTypeArguments();
|
||||
assert
|
||||
tas.length == 1 :
|
||||
"The type of parameter 2 of mc1t has one type argument";
|
||||
Type ta = tas[0];
|
||||
|
||||
assert
|
||||
ta instanceof TypeVariable :
|
||||
"The actual type arg of C1<T> is a type variable (mc1t)";
|
||||
tv = (TypeVariable) ta;
|
||||
assert
|
||||
tv.getName().equals("T") :
|
||||
"mc1t: Name of the type arg of C1<T> is T, not " + tv.getName();
|
||||
bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"mc1t: The type argument of C1<T> should have one bound";
|
||||
assert
|
||||
bs[0] == Object.class :
|
||||
"mc1t: The bound of the type arg of C1<T> should be Object";
|
||||
|
||||
Type p3_mc1t = pt_mc1t[2];
|
||||
|
||||
assert
|
||||
p3_mc1t == cls :
|
||||
"Type of parameter 3 of mc1t is C1";
|
||||
|
||||
Type[] pt_mc1 = mc1.getGenericParameterTypes();
|
||||
assert
|
||||
pt_mc1.length == 0 :
|
||||
"C1.mc1 has zero parameters";
|
||||
|
||||
Type[] pt_mt = mt.getGenericParameterTypes();
|
||||
assert
|
||||
pt_mt.length == 1 :
|
||||
"C1.mt has one parameter";
|
||||
Type p_mt = pt_mt[0];
|
||||
assert
|
||||
p_mt instanceof TypeVariable :
|
||||
"The generic type of the parameter of mt(T) is a type variable";
|
||||
tv = (TypeVariable) p_mt;
|
||||
assert
|
||||
tv.getName().equals("T") :
|
||||
"The name of the type parameter of mt is T, not " + tv.getName();
|
||||
bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T should have one bound";
|
||||
assert
|
||||
bs[0] == Object.class :
|
||||
"The bound of T should be Object";
|
||||
|
||||
Type[] et_mc1t = mc1t.getGenericExceptionTypes();
|
||||
assert
|
||||
et_mc1t.length == 0 :
|
||||
"Method C1.mc1t should have no generic exception types";
|
||||
|
||||
Type[] et_mc1 = mc1.getGenericExceptionTypes();
|
||||
assert
|
||||
et_mc1.length == 0 :
|
||||
"Method C1.mc1 should have no generic exception types";
|
||||
|
||||
Type[] et_mt = mt.getGenericExceptionTypes();
|
||||
|
||||
assert
|
||||
et_mt.length == 0 :
|
||||
"Method C1.mt should have no generic exception types";
|
||||
|
||||
|
||||
TypeVariable[] tv_mc1t = mc1t.getTypeParameters();
|
||||
assert
|
||||
tv_mc1t.length == 0 :
|
||||
"Method C1.mc1t should have no type parameters";
|
||||
|
||||
TypeVariable[] tv_mc1 = mc1.getTypeParameters();
|
||||
assert
|
||||
tv_mc1.length == 0 :
|
||||
"Method C1.mc1 should have no type parameters";
|
||||
|
||||
TypeVariable[] tv_mt = mt.getTypeParameters();
|
||||
assert
|
||||
tv_mt.length == 0 :
|
||||
"Method C1.mt should have no type parameters";
|
||||
}
|
||||
|
||||
|
||||
static void testFields() throws NoSuchFieldException{
|
||||
System.out.println("testing fields");
|
||||
Field ft = cls. getField("ft");
|
||||
Field fc1t = cls. getField("fc1t");
|
||||
Field fc1 = cls. getField("fc1");
|
||||
|
||||
Type gt_ft = ft.getGenericType();
|
||||
assert
|
||||
gt_ft instanceof TypeVariable :
|
||||
"The generic type of C1.ft is a type variable";
|
||||
TypeVariable tv = (TypeVariable) gt_ft;
|
||||
assert
|
||||
tv.getName().equals("T") :
|
||||
"The name of the type of ft is T, not " + tv.getName();
|
||||
Type[] bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"The type of ft should have one bound";
|
||||
assert
|
||||
bs[0] == Object.class :
|
||||
"The bound of the type of ft should be Object";
|
||||
|
||||
Type gt_fc1t = fc1t.getGenericType();
|
||||
assert
|
||||
gt_fc1t instanceof ParameterizedType :
|
||||
"The generic type of C1.fc1t is a parameterized type";
|
||||
ParameterizedType pt = (ParameterizedType) gt_fc1t;
|
||||
assert
|
||||
pt.getRawType() == cls :
|
||||
"Type of C1.fc1t is instantiation of C1";
|
||||
assert
|
||||
pt.getOwnerType() == null :
|
||||
"Type of C1.fc1t is has null owner";
|
||||
Type[] tas = pt.getActualTypeArguments();
|
||||
assert
|
||||
tas.length == 1 :
|
||||
"The type of fc1t has one type argument";
|
||||
Type ta = tas[0];
|
||||
|
||||
assert
|
||||
ta instanceof TypeVariable :
|
||||
"The actual type arg of C1<T> is a type variable";
|
||||
tv = (TypeVariable) ta;
|
||||
assert
|
||||
tv.getName().equals("T") :
|
||||
"The name of the type arg of C1<T> is T, not " + tv.getName();
|
||||
bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"The type argument of C1<T> should have one bound";
|
||||
assert
|
||||
bs[0] == Object.class :
|
||||
"The bound of the type arg of C1<T> should be Object";
|
||||
|
||||
Type gt_fc1 = fc1.getGenericType();
|
||||
assert
|
||||
gt_fc1 == cls :
|
||||
" Type of C1.fc1 should be C1";
|
||||
}
|
||||
|
||||
static void testConstructor() throws NoSuchMethodException {
|
||||
System.out.println("testing constructors");
|
||||
Class[] params = new Class[1];
|
||||
params[0] = Object.class;
|
||||
Constructor<C1> con = cls.getDeclaredConstructor(params);
|
||||
|
||||
Type[] pt_con = con.getGenericParameterTypes();
|
||||
assert
|
||||
pt_con.length == 1 :
|
||||
"Constructor C1(T) should have one generic parameter type";
|
||||
Type pt = pt_con[0];
|
||||
assert
|
||||
pt instanceof TypeVariable :
|
||||
"The generic type of the parameter of C1(T) is a type variable";
|
||||
TypeVariable tv = (TypeVariable) pt;
|
||||
assert
|
||||
tv.getName().equals("T") :
|
||||
"The name of the type parameter of C is T, not " + tv.getName();
|
||||
Type[] bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T should have one bound";
|
||||
assert
|
||||
bs[0] == Object.class :
|
||||
"The bound of T should be Object";
|
||||
|
||||
Type[] et_con = con.getGenericExceptionTypes();
|
||||
assert
|
||||
et_con.length == 0 :
|
||||
"Constructor C1(T) should have no generic exception types";
|
||||
|
||||
TypeVariable[] tv_con = con.getTypeParameters();
|
||||
assert
|
||||
tv_con.length == 0 :
|
||||
"Constructor C1(T) should have no type parameters";
|
||||
|
||||
}
|
||||
}
|
||||
653
test/jdk/java/lang/reflect/Generics/TestC2.java
Normal file
653
test/jdk/java/lang/reflect/Generics/TestC2.java
Normal file
|
|
@ -0,0 +1,653 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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 4891872
|
||||
* @summary Some tests for the generic core reflection api.
|
||||
* @author Gilad Bracha
|
||||
* @compile TestC2.java
|
||||
* @run main/othervm -ea TestC2
|
||||
*/
|
||||
|
||||
|
||||
import java.lang.reflect.*;
|
||||
|
||||
|
||||
abstract class C0<T> {
|
||||
|
||||
public T ft;
|
||||
public C0<T> fc1t;
|
||||
public C0 fc1;
|
||||
|
||||
public C0(){}
|
||||
public C0(T t) {}
|
||||
|
||||
public abstract C0<T> mc1t(T t, C0<T> c1t, C0 c1);
|
||||
|
||||
public abstract C0 mc1();
|
||||
|
||||
public abstract T mt(T t);
|
||||
|
||||
}
|
||||
|
||||
interface I1<X1, X2> extends I3 {
|
||||
|
||||
X1 foo(X2 x2);
|
||||
}
|
||||
|
||||
interface I2<E1, E2 extends Throwable, E3> {
|
||||
|
||||
|
||||
E1 bar(E3 e3) throws E2;
|
||||
|
||||
}
|
||||
|
||||
interface I3 {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
abstract class C2<T1 extends C2<T1, T2, T3>, T2 extends C0<T2>,
|
||||
T3 extends Throwable>
|
||||
extends C0<T1>
|
||||
implements I1<T1, T2>, I2<T1, T3, T2>, I3
|
||||
{
|
||||
|
||||
public T1 ft;
|
||||
public C0<String> fc1t;
|
||||
public C0 fc1;
|
||||
public int fi;
|
||||
|
||||
public C2(T2 t2) {}
|
||||
public <T> C2(T t) {}
|
||||
public <T1, T2, T3, T4> C2(T1 t1, T2 t2, T4 t4) {}
|
||||
public C2() throws T3 {}
|
||||
|
||||
public abstract <T> C0<T> mc1t(T3 t3, C0<T> c1t, C0 c1);
|
||||
|
||||
public abstract <E, R> C0 mc1(E e);
|
||||
|
||||
public abstract T1 mt(T2 t);
|
||||
|
||||
}
|
||||
|
||||
public class TestC2 {
|
||||
|
||||
static Class<C2> cls = C2.class;
|
||||
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
testSuperclass();
|
||||
testSuperInterfaces();
|
||||
testTypeParameters();
|
||||
testMethods();
|
||||
testConstructors();
|
||||
testFields();
|
||||
}
|
||||
|
||||
static void testSuperclass() {
|
||||
|
||||
System.out.println("testing superclass");
|
||||
Type sc = cls.getGenericSuperclass();
|
||||
assert
|
||||
sc instanceof ParameterizedType :
|
||||
"Superclass of C2 should be a parameterized type";
|
||||
ParameterizedType psc = (ParameterizedType) sc;
|
||||
assert
|
||||
((psc.getRawType() == C0.class) ) :
|
||||
"The raw generic superclass of C2 should be C0";
|
||||
|
||||
Type[] tas = psc.getActualTypeArguments();
|
||||
assert
|
||||
tas.length == 1 :
|
||||
"Superclass of C2 should have one type argument";
|
||||
|
||||
Type t = tas[0];
|
||||
|
||||
assert
|
||||
t instanceof TypeVariable :
|
||||
"Type argument to superclass of C2 should be a type variable";
|
||||
|
||||
TypeVariable tv = (TypeVariable) t;
|
||||
assert
|
||||
tv.getName().equals("T1") :
|
||||
"Name of type argument to superclass of C2 should be T1";
|
||||
Type[] bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T1 has one bound (superclass)";
|
||||
t = bs[0];
|
||||
assert
|
||||
t instanceof ParameterizedType :
|
||||
"Bound of C0 should be a parameterized type";
|
||||
ParameterizedType pt = (ParameterizedType) t;
|
||||
|
||||
assert
|
||||
((pt.getRawType() == C2.class) ) :
|
||||
"The raw bound of T1 should be C2";
|
||||
|
||||
tas = pt.getActualTypeArguments();
|
||||
assert
|
||||
tas.length == 3 :
|
||||
"Bound of T1 should have three type arguments";
|
||||
assert
|
||||
tas[0] instanceof TypeVariable :
|
||||
"First argument to bound of T1 is a type variable";
|
||||
assert
|
||||
tas[1] instanceof TypeVariable :
|
||||
"Second argument to bound of T1 is a type variable";
|
||||
assert
|
||||
tas[2] instanceof TypeVariable :
|
||||
"Third argument to bound of T1 is a type variable";
|
||||
|
||||
TypeVariable tv1 = (TypeVariable) tas[0];
|
||||
TypeVariable tv2 = (TypeVariable) tas[1];
|
||||
TypeVariable tv3 = (TypeVariable) tas[2];
|
||||
|
||||
assert
|
||||
tv1.getName().equals("T1"):
|
||||
"First type arg to bound of T1 is T1";
|
||||
assert
|
||||
tv2.getName().equals("T2"):
|
||||
"Seconmd type arg to bound of T1 is T2";
|
||||
assert
|
||||
tv3.getName().equals("T3"):
|
||||
"Third type arg to bound of T1 is T3";
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testSuperInterfaces() {
|
||||
System.out.println("testing superinterfaces");
|
||||
Type[] sis = cls.getGenericInterfaces();
|
||||
assert
|
||||
((sis.length == 3)):
|
||||
"C2 should have three generic superinterfaces";
|
||||
|
||||
Type t = sis[0];
|
||||
assert
|
||||
t instanceof ParameterizedType :
|
||||
"First superinterface of C2 should be a parameterized type";
|
||||
ParameterizedType pt = (ParameterizedType) t;
|
||||
assert
|
||||
pt.getRawType() == I1.class :
|
||||
"First super interface of C2 is instantiation of I1";
|
||||
Type[] tas = pt.getActualTypeArguments();
|
||||
assert
|
||||
tas.length == 2 :
|
||||
"First super interface of C2 has 2 type arguments";
|
||||
|
||||
t = sis[1];
|
||||
assert
|
||||
t instanceof ParameterizedType :
|
||||
"Second superinterface of C2 should be a parameterized type";
|
||||
pt = (ParameterizedType) t;
|
||||
assert
|
||||
pt.getRawType() == I2.class :
|
||||
"Second super interface of C2 is instantiation of I2";
|
||||
tas = pt.getActualTypeArguments();
|
||||
assert
|
||||
tas.length == 3 :
|
||||
"Second super interface of C2 has 3 type arguments";
|
||||
|
||||
t = sis[2];
|
||||
assert
|
||||
t == I3.class :
|
||||
"Third superinterface of C2 is I3";
|
||||
|
||||
// Test interfaces themselves
|
||||
|
||||
TypeVariable[] tvs = I1.class.getTypeParameters();
|
||||
assert
|
||||
tvs.length == 2 :
|
||||
"I3 has two formal type parameters";
|
||||
assert
|
||||
tvs[0].getName().equals("X1") :
|
||||
"Name of first formal type arg of I1 is X1";
|
||||
assert
|
||||
tvs[1].getName().equals("X2") :
|
||||
"Name of second formal type arg of I1 is X2";
|
||||
|
||||
assert
|
||||
I1.class.getGenericSuperclass() == I1.class.getSuperclass() :
|
||||
"The generic and non-generic superclasses of an interface must be the same";
|
||||
sis = I1.class.getGenericInterfaces();
|
||||
assert
|
||||
sis.length == 1 :
|
||||
"I1 has one generic superinterface";
|
||||
assert
|
||||
sis[0] == I3.class :
|
||||
"Superinterface of I1 is I3";
|
||||
|
||||
tvs = I2.class.getTypeParameters();
|
||||
assert
|
||||
tvs.length == 3 :
|
||||
"I3 has three formal type parameters";
|
||||
assert
|
||||
tvs[0].getName().equals("E1") :
|
||||
"Name of first formal type arg of I2 is E1";
|
||||
assert
|
||||
tvs[1].getName().equals("E2") :
|
||||
"Name of second formal type arg of I2 is E2";
|
||||
assert
|
||||
tvs[2].getName().equals("E3") :
|
||||
"Name of third formal type arg of I2 is E3";
|
||||
|
||||
assert
|
||||
I2.class.getGenericSuperclass() == I2.class.getSuperclass() :
|
||||
"The generic and non-generic superclasses of an interface must be the same";
|
||||
|
||||
tvs = I3.class.getTypeParameters();
|
||||
assert
|
||||
tvs.length == 0 :
|
||||
"I3 has no formal type parameters";
|
||||
|
||||
assert
|
||||
I3.class.getGenericSuperclass() == I3.class.getSuperclass() :
|
||||
"The generic and non-generic superclasses of an interface must be the same";
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testTypeParameters() {
|
||||
System.out.println("testing type parameters");
|
||||
TypeVariable[] tvs = cls.getTypeParameters();
|
||||
assert
|
||||
tvs.length == 3 :
|
||||
"C2 should have three type parameters";
|
||||
TypeVariable tv = tvs[0];
|
||||
Type[] bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T1 should have one bound";
|
||||
assert
|
||||
bs[0] instanceof ParameterizedType :
|
||||
"The bound of T1 should be a parameterized type";
|
||||
|
||||
tv = tvs[1];
|
||||
bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T2 should have one bound";
|
||||
assert
|
||||
bs[0] instanceof ParameterizedType :
|
||||
"The bound of T2 should be a parameterized type";
|
||||
|
||||
tv = tvs[2];
|
||||
bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T3 should have one bound";
|
||||
assert
|
||||
bs[0] == Throwable.class :
|
||||
"The bound of T3 should be Throwable";
|
||||
}
|
||||
|
||||
static void testMethods() throws NoSuchMethodException {
|
||||
System.out.println("testing methods");
|
||||
|
||||
|
||||
|
||||
Class[] params1 = new Class[3];
|
||||
params1[0] = Throwable.class;
|
||||
params1[1] = C0.class;
|
||||
params1[2] = C0.class;
|
||||
|
||||
Class[] params2 = new Class[1];
|
||||
params2[0] = Object.class;
|
||||
|
||||
Class[] params3 = new Class[1];
|
||||
params3[0] = C0.class;
|
||||
|
||||
Method mc1t = cls.getMethod("mc1t", params1);
|
||||
Method mc1 = cls.getMethod("mc1", params2);
|
||||
Method mt = cls.getMethod("mt", params3);
|
||||
|
||||
Type rt_mc1t = mc1t.getGenericReturnType();
|
||||
assert
|
||||
rt_mc1t instanceof ParameterizedType :
|
||||
"The return type of mc1t should be a parameterized type";
|
||||
ParameterizedType pt = (ParameterizedType) rt_mc1t;
|
||||
|
||||
assert
|
||||
pt.getRawType() == C0.class :
|
||||
"The raw return type of mc1t should be C0";
|
||||
|
||||
Type[] tas = pt.getActualTypeArguments();
|
||||
assert
|
||||
tas.length == 1 :
|
||||
"Return type of mc1t should have one type argument";
|
||||
assert
|
||||
tas[0] instanceof TypeVariable :
|
||||
"Type argument of return type of mc1t is a type variable";
|
||||
|
||||
Type rt_mc1 = mc1.getGenericReturnType();
|
||||
assert
|
||||
rt_mc1 == C0.class :
|
||||
"Return type of mc1 is C0";
|
||||
|
||||
Type rt_mt = mt.getGenericReturnType();
|
||||
assert
|
||||
rt_mt instanceof TypeVariable :
|
||||
"Return type of mt is a type variable";
|
||||
|
||||
Type[] pt_mc1t = mc1t.getGenericParameterTypes();
|
||||
|
||||
assert
|
||||
pt_mc1t.length == 3 :
|
||||
"C0.mc1t has three parameters";
|
||||
Type p1_mc1t = pt_mc1t[0];
|
||||
assert p1_mc1t != null;
|
||||
assert
|
||||
p1_mc1t instanceof TypeVariable :
|
||||
"Generic type of the 1st parameter of mc1t(T) is a type variable";
|
||||
TypeVariable tv = (TypeVariable) p1_mc1t;
|
||||
|
||||
assert
|
||||
tv.getName().equals("T3") :
|
||||
"Name of 1st type parameter of mc1t is T3, not " + tv.getName();
|
||||
Type[] bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T3 should have one bound (mc1t)";
|
||||
assert
|
||||
bs[0] == Throwable.class :
|
||||
"The bound of T3 should be Throwable(mc1t)";
|
||||
|
||||
Type p2_mc1t = pt_mc1t[1];
|
||||
assert
|
||||
p2_mc1t instanceof ParameterizedType :
|
||||
"The type of parameter 2 of mc1t is a parameterized type";
|
||||
pt = (ParameterizedType) p2_mc1t;
|
||||
assert
|
||||
pt.getRawType() == C0.class :
|
||||
"Type of parameter 2 of mc1t is instantiation of C0";
|
||||
assert
|
||||
pt.getOwnerType() == null :
|
||||
"Type of parameter 2 of mc1t is has null owner";
|
||||
|
||||
tas = pt.getActualTypeArguments();
|
||||
assert
|
||||
tas.length == 1 :
|
||||
"The type of parameter 2 of mc1t has one type argument";
|
||||
Type ta = tas[0];
|
||||
|
||||
assert
|
||||
ta instanceof TypeVariable :
|
||||
"The actual type arg of C0<T> is a type variable (mc1t)";
|
||||
tv = (TypeVariable) ta;
|
||||
assert
|
||||
tv.getName().equals("T") :
|
||||
"mc1t: Name of the type arg of C0<T> is T, not " + tv.getName();
|
||||
bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"mc1t: The type argument of C0<T> should have one bound";
|
||||
assert
|
||||
bs[0] == Object.class :
|
||||
"mc1t: The bound of the type arg of C0<T> should be Object";
|
||||
|
||||
Type p3_mc1t = pt_mc1t[2];
|
||||
assert
|
||||
p3_mc1t == C0.class :
|
||||
"Type of parameter 3 of mc1t is C0";
|
||||
|
||||
Type[] pt_mc1 = mc1.getGenericParameterTypes();
|
||||
assert
|
||||
pt_mc1.length == 1 :
|
||||
"C2.mc1 has one parameter";
|
||||
|
||||
Type[] pt_mt = mt.getGenericParameterTypes();
|
||||
assert
|
||||
pt_mt.length == 1 :
|
||||
"C2.mt has one parameter";
|
||||
Type p_mt = pt_mt[0];
|
||||
assert
|
||||
p_mt instanceof TypeVariable :
|
||||
"The generic type of the parameter of mt(T) is a type variable";
|
||||
tv = (TypeVariable) p_mt;
|
||||
assert
|
||||
tv.getName().equals("T2") :
|
||||
"The name of the type parameter of mt is T2, not " + tv.getName();
|
||||
bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T2 should have one bound";
|
||||
assert
|
||||
bs[0] instanceof ParameterizedType:
|
||||
"The bound of T2 should be parameterized type";
|
||||
|
||||
Type[] et_mc1t = mc1t.getGenericExceptionTypes();
|
||||
assert
|
||||
et_mc1t.length == 0 :
|
||||
"Method C0.mc1t should have no generic exception types";
|
||||
|
||||
Type[] et_mc1 = mc1.getGenericExceptionTypes();
|
||||
assert
|
||||
et_mc1.length == 0 :
|
||||
"Method C0.mc1 should have no generic exception types";
|
||||
|
||||
Type[] et_mt = mt.getGenericExceptionTypes();
|
||||
assert
|
||||
et_mt.length == 0 :
|
||||
"Method C0.mt should have no generic exception types";
|
||||
|
||||
|
||||
TypeVariable[] tv_mc1t = mc1t.getTypeParameters();
|
||||
assert
|
||||
tv_mc1t.length == 1 :
|
||||
"Method C2.mc1t should have one type parameter";
|
||||
|
||||
TypeVariable[] tv_mc1 = mc1.getTypeParameters();
|
||||
assert
|
||||
tv_mc1.length == 2 :
|
||||
"Method C2.mc1 should have two type parameters";
|
||||
|
||||
TypeVariable[] tv_mt = mt.getTypeParameters();
|
||||
assert
|
||||
tv_mt.length == 0 :
|
||||
"Method C2.mt should have no type parameters";
|
||||
}
|
||||
|
||||
|
||||
static void testFields() throws NoSuchFieldException{
|
||||
System.out.println("testing fields");
|
||||
Field ft = cls. getField("ft");
|
||||
Field fc1t = cls. getField("fc1t");
|
||||
Field fc1 = cls. getField("fc1");
|
||||
Field fi = cls. getField("fi");
|
||||
|
||||
Type gt_ft = ft.getGenericType();
|
||||
assert
|
||||
gt_ft instanceof TypeVariable :
|
||||
"The generic type of C0.ft is a type variable";
|
||||
TypeVariable tv = (TypeVariable) gt_ft;
|
||||
assert
|
||||
tv.getName().equals("T1") :
|
||||
"The name of the type of ft is T1, not " + tv.getName();
|
||||
Type[] bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"The type of ft should have one bound";
|
||||
|
||||
|
||||
Type gt_fc1t = fc1t.getGenericType();
|
||||
assert
|
||||
gt_fc1t instanceof ParameterizedType :
|
||||
"The generic type of C0.fc1t is a parameterized type";
|
||||
ParameterizedType pt = (ParameterizedType) gt_fc1t;
|
||||
assert
|
||||
pt.getRawType() == C0.class :
|
||||
"Type of C2.fc1t is an instantiation of C0";
|
||||
assert
|
||||
pt.getOwnerType() == null :
|
||||
"Type of C2.fc1t is has null owner";
|
||||
Type[] tas = pt.getActualTypeArguments();
|
||||
assert
|
||||
tas.length == 1 :
|
||||
"The type of fc1t has one type argument";
|
||||
Type ta = tas[0];
|
||||
|
||||
assert
|
||||
ta == String.class :
|
||||
"The actual type arg of C0<String> is String";
|
||||
|
||||
|
||||
Type gt_fc1 = fc1.getGenericType();
|
||||
assert
|
||||
gt_fc1 == C0.class :
|
||||
" Type of C2.fc1 should be C0";
|
||||
|
||||
Type gt_fi = fi.getGenericType();
|
||||
assert
|
||||
gt_fi == int.class:
|
||||
" Type of C2.fi should be int";
|
||||
|
||||
}
|
||||
|
||||
static void testConstructors() throws NoSuchMethodException {
|
||||
System.out.println("testing constructors");
|
||||
Class[] params1 = new Class[1];
|
||||
params1[0] = C0.class;
|
||||
Constructor<C2> con = cls.getDeclaredConstructor(params1);
|
||||
|
||||
Type[] pt_con = con.getGenericParameterTypes();
|
||||
assert
|
||||
pt_con.length == 1 :
|
||||
"Constructor C0(T) should have one generic parameter type";
|
||||
Type pt = pt_con[0];
|
||||
assert
|
||||
pt instanceof TypeVariable :
|
||||
"The generic type of the parameter of C0(T2) is a type variable";
|
||||
TypeVariable tv = (TypeVariable) pt;
|
||||
assert
|
||||
tv.getName().equals("T2") :
|
||||
"The name of the type parameter of C2 is T2, not " + tv.getName();
|
||||
Type[] bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T should have one bound";
|
||||
|
||||
|
||||
Type[] et_con = con.getGenericExceptionTypes();
|
||||
assert
|
||||
et_con.length == 0 :
|
||||
"Constructor C2(T2) should have no generic exception types";
|
||||
|
||||
TypeVariable[] tv_con = con.getTypeParameters();
|
||||
assert
|
||||
tv_con.length == 0 :
|
||||
"Constructor C2(T2) should have no type parameters";
|
||||
|
||||
|
||||
Class[] params2 = new Class[1];
|
||||
params2[0] = Object.class;
|
||||
con = cls.getDeclaredConstructor(params2);
|
||||
|
||||
pt_con = con.getGenericParameterTypes();
|
||||
assert
|
||||
pt_con.length == 1 :
|
||||
"Constructor C0(T) should have one generic parameter type";
|
||||
pt = pt_con[0];
|
||||
assert
|
||||
pt instanceof TypeVariable :
|
||||
"The generic type of the parameter of C2(T) is a type variable";
|
||||
tv = (TypeVariable) pt;
|
||||
assert
|
||||
tv.getName().equals("T") :
|
||||
"The name of the type parameter of C2 is T, not " + tv.getName();
|
||||
bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T should have one bound";
|
||||
|
||||
|
||||
et_con = con.getGenericExceptionTypes();
|
||||
assert
|
||||
et_con.length == 0 :
|
||||
"Constructor C2(T) should have no generic exception types";
|
||||
|
||||
tv_con = con.getTypeParameters();
|
||||
assert
|
||||
tv_con.length == 1 :
|
||||
"Constructor C2(T) should have one type parameter";
|
||||
|
||||
Class[] params3 = new Class[3];
|
||||
params3[0] = Object.class;
|
||||
params3[1] = Object.class;
|
||||
params3[2] = Object.class;
|
||||
|
||||
con = cls.getDeclaredConstructor(params3);
|
||||
|
||||
pt_con = con.getGenericParameterTypes();
|
||||
assert
|
||||
pt_con.length == 3 :
|
||||
"Constructor C2(T1,T2,T4) should have three generic parameter types";
|
||||
pt = pt_con[0];
|
||||
assert
|
||||
pt instanceof TypeVariable :
|
||||
"The generic type of the first parameter of C2(T1,T2,T4) is a type variable";
|
||||
tv = (TypeVariable) pt;
|
||||
assert
|
||||
tv.getName().equals("T1") :
|
||||
"The name of the type parameter of C2(T1,T2,T4) is T1, not " + tv.getName();
|
||||
bs = tv.getBounds();
|
||||
assert
|
||||
bs.length == 1 :
|
||||
"T should have one bound";
|
||||
|
||||
|
||||
et_con = con.getGenericExceptionTypes();
|
||||
assert
|
||||
et_con.length == 0 :
|
||||
"Constructor C2(T1,T2,T4) should have no generic exception types";
|
||||
|
||||
tv_con = con.getTypeParameters();
|
||||
assert
|
||||
tv_con.length == 4 :
|
||||
"Constructor C2(T1,T2,T4) should have four type parameters";
|
||||
|
||||
Class[] params4 = new Class[0];
|
||||
con = cls.getDeclaredConstructor(params4);
|
||||
|
||||
pt_con = con.getGenericParameterTypes();
|
||||
assert
|
||||
pt_con.length == 0 :
|
||||
"Constructor C2() should have no generic parameter types";
|
||||
|
||||
|
||||
et_con = con.getGenericExceptionTypes();
|
||||
assert
|
||||
et_con.length == 1 :
|
||||
"Constructor C2() should have one generic exception type";
|
||||
|
||||
tv_con = con.getTypeParameters();
|
||||
assert
|
||||
tv_con.length == 0 :
|
||||
"Constructor C2() should have no type parameters";
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* 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 8054213
|
||||
* @summary Check that toString method works properly for generic return type
|
||||
* obtained via reflection
|
||||
* @run main TestGenericReturnTypeToString
|
||||
*/
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
public class TestGenericReturnTypeToString {
|
||||
|
||||
public static void main(String[] args) {
|
||||
boolean hasFailures = false;
|
||||
for (Method method : TestGenericReturnTypeToString.class.getMethods()) {
|
||||
if (method.isAnnotationPresent(ExpectedGenericString.class)) {
|
||||
ExpectedGenericString es = method.getAnnotation
|
||||
(ExpectedGenericString.class);
|
||||
String result = method.getGenericReturnType().toString();
|
||||
if (!es.value().equals(result)) {
|
||||
hasFailures = true;
|
||||
System.err.println("Unexpected result of " +
|
||||
"getGenericReturnType().toString() " +
|
||||
" for " + method.getName()
|
||||
+ " expected: " + es.value() + " actual: " + result);
|
||||
}
|
||||
}
|
||||
if (hasFailures) {
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ExpectedGenericString("TestGenericReturnTypeToString$" +
|
||||
"FirstInnerClassGeneric<Dummy>$SecondInnerClassGeneric<Dummy>")
|
||||
public FirstInnerClassGeneric<Dummy>.SecondInnerClassGeneric<Dummy> foo1() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ExpectedGenericString("TestGenericReturnTypeToString$" +
|
||||
"FirstInnerClassGeneric<Dummy>$SecondInnerClass")
|
||||
public FirstInnerClassGeneric<Dummy>.SecondInnerClass foo2() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ExpectedGenericString("TestGenericReturnTypeToString$" +
|
||||
"FirstInnerClass$SecondInnerClassGeneric<Dummy>")
|
||||
public FirstInnerClass.SecondInnerClassGeneric<Dummy> foo3() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ExpectedGenericString("class TestGenericReturnTypeToString$" +
|
||||
"FirstInnerClass$SecondInnerClass")
|
||||
public FirstInnerClass.SecondInnerClass foo4() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ExpectedGenericString(
|
||||
"java.util.List<java.lang.String>")
|
||||
public java.util.List<java.lang.String> foo5() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ExpectedGenericString("interface TestGenericReturnTypeToString$" +
|
||||
"FirstInnerClass$Interface")
|
||||
public FirstInnerClass.Interface foo6() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ExpectedGenericString("TestGenericReturnTypeToString$" +
|
||||
"FirstInnerClass$InterfaceGeneric<Dummy>")
|
||||
public FirstInnerClass.InterfaceGeneric<Dummy> foo7() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class FirstInnerClass {
|
||||
|
||||
public class SecondInnerClassGeneric<T> {
|
||||
}
|
||||
|
||||
public class SecondInnerClass {
|
||||
}
|
||||
|
||||
interface Interface {
|
||||
}
|
||||
|
||||
interface InterfaceGeneric<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public class FirstInnerClassGeneric<T> {
|
||||
|
||||
public class SecondInnerClassGeneric<T> {
|
||||
}
|
||||
|
||||
public class SecondInnerClass {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface ExpectedGenericString {
|
||||
String value();
|
||||
}
|
||||
|
||||
class Dummy {
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 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
|
||||
* @library /test/lib
|
||||
* @bug 8337302
|
||||
* @summary Tests that an exception is thrown if a type variable is not declared
|
||||
*/
|
||||
|
||||
import jdk.test.lib.ByteCodeLoader;
|
||||
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.Signature;
|
||||
import java.lang.classfile.attribute.SignatureAttribute;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.reflect.AccessFlag;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class TestMissingTypeVariable {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ClassFile cf = ClassFile.of();
|
||||
byte[] bytes = cf.build(
|
||||
ClassDesc.of("sample.MissingVariable"),
|
||||
classBuilder -> {
|
||||
classBuilder.withSuperclass(ClassDesc.of("java.lang.Object"));
|
||||
classBuilder.withFlags(AccessFlag.PUBLIC);
|
||||
classBuilder.withField("f",
|
||||
ClassDesc.of("java.lang.Object"),
|
||||
fieldBuilder -> fieldBuilder.withFlags(AccessFlag.PUBLIC).with(SignatureAttribute.of(Signature.parseFrom("TA;"))));
|
||||
});
|
||||
/*
|
||||
package sample;
|
||||
public class MissingVariable {
|
||||
public A f; // undeclared type variable
|
||||
}
|
||||
*/
|
||||
Class<?> missing = ByteCodeLoader.load("sample.MissingVariable", bytes);
|
||||
try {
|
||||
Type type = missing.getField("f").getGenericType();
|
||||
throw new IllegalStateException("Expected TypeNotPresentException but got: " + type);
|
||||
} catch (TypeNotPresentException e) {
|
||||
if (!"A".equals(e.typeName())) {
|
||||
throw new IllegalStateException("Unexpected name: " + e.typeName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
207
test/jdk/java/lang/reflect/Generics/TestN1.java
Normal file
207
test/jdk/java/lang/reflect/Generics/TestN1.java
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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 4891872
|
||||
* @summary Some tests for the generic core reflection api.
|
||||
* @author Gilad Bracha
|
||||
* @compile TestN1.java
|
||||
* @run main/othervm -ea TestN1
|
||||
*/
|
||||
|
||||
|
||||
import java.lang.reflect.*;
|
||||
|
||||
|
||||
class N1<T1, T2> {
|
||||
|
||||
public Inner1 i1;
|
||||
public Inner2 i2;
|
||||
public Inner2<? super Character> i2sc;
|
||||
|
||||
public class Inner1 {
|
||||
|
||||
}
|
||||
|
||||
public class Inner2<T1> {
|
||||
public boolean x;
|
||||
public byte b;
|
||||
public short s;
|
||||
public char c;
|
||||
public int i;
|
||||
public long l;
|
||||
public float f;
|
||||
public double d;
|
||||
|
||||
public boolean[] xa;
|
||||
public byte[] ba;
|
||||
public short[] sa;
|
||||
public char[] ca;
|
||||
public int[] ia;
|
||||
public long[] la;
|
||||
public float[] fa;
|
||||
public double[] da;
|
||||
}
|
||||
|
||||
public class Inner3<X1, X2, X3> {
|
||||
X1 x1;
|
||||
|
||||
Inner3(X1 x1, X2 x2, X3 x3, T1 t1, T2 t2) {}
|
||||
|
||||
<T, R, S> Inner3(T t, R r, S s, X1 x1) {}
|
||||
|
||||
int shazam(boolean b, short s, int[] ia, Object[] oa, Inner1 i1,
|
||||
Inner1 i1a, InnerInner<String,
|
||||
Inner3<Object, String, Object[]>> ii)
|
||||
{ return 3;}
|
||||
|
||||
public class InnerInner<T2, X2> {
|
||||
|
||||
boolean b;
|
||||
Inner2<X2> i2x;
|
||||
|
||||
void foo(X3 x3){}
|
||||
<X3> X3[] bar(X1 x1, X3[] x3, T1 t1) { return x3;}
|
||||
N1<X1, X2> baz(N1<X1, X2> n1) { return n1;}
|
||||
N1<?, ?> bam(N1<T1, X2> n1) { return n1;}
|
||||
N1<? extends T1, ?> boom(N1<T1, X2> n1) { return n1;}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class TestN1 {
|
||||
|
||||
static Class<N1> cls = N1.class;
|
||||
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
testTypeParameters();
|
||||
testInner1();
|
||||
testInner2();
|
||||
testInner3();
|
||||
}
|
||||
|
||||
|
||||
static void testTypeParameters() {
|
||||
|
||||
System.out.println("testing type parameters");
|
||||
TypeVariable[] tvs = cls.getTypeParameters();
|
||||
assert
|
||||
tvs.length == 2 :
|
||||
"N1 should have two type parameters";
|
||||
}
|
||||
|
||||
|
||||
static void testInner1() {
|
||||
System.out.println("testing non-generic inner class");
|
||||
Class in1 = N1.Inner1.class;
|
||||
|
||||
TypeVariable[] tvs = in1.getTypeParameters();
|
||||
assert
|
||||
tvs.length == 0 :
|
||||
"N1.Inner2 should have no type parameters";
|
||||
|
||||
}
|
||||
|
||||
static void testInner2() throws NoSuchFieldException {
|
||||
System.out.println("testing generic inner class 1");
|
||||
Class in1 = N1.Inner2.class;
|
||||
|
||||
TypeVariable[] tvs = in1.getTypeParameters();
|
||||
assert
|
||||
tvs.length == 1 :
|
||||
"N1.Inner2 should have one type parameter";
|
||||
|
||||
|
||||
assert
|
||||
in1.getField("x").getGenericType() == boolean.class :
|
||||
"Type of Inner2.x should be boolean";
|
||||
|
||||
assert
|
||||
in1.getField("b").getGenericType() == byte.class :
|
||||
"Type of Inner2.b should be byte";
|
||||
assert
|
||||
in1.getField("s").getGenericType() == short.class :
|
||||
"Type of Inner2.s should be short";
|
||||
assert
|
||||
in1.getField("c").getGenericType() == char.class :
|
||||
"Type of Inner2.x should be char";
|
||||
assert
|
||||
in1.getField("i").getGenericType() == int.class :
|
||||
"Type of Inner2.i should be int";
|
||||
assert
|
||||
in1.getField("l").getGenericType() == long.class :
|
||||
"Type of Inner2.l should be long";
|
||||
assert
|
||||
in1.getField("f").getGenericType() == float.class :
|
||||
"Type of Inner2.f should be float";
|
||||
assert
|
||||
in1.getField("d").getGenericType() == double.class :
|
||||
"Type of Inner2.d should be double";
|
||||
|
||||
assert
|
||||
in1.getField("xa").getGenericType() == boolean[].class :
|
||||
"Type of Inner2.xa should be boolean[]";
|
||||
|
||||
assert
|
||||
in1.getField("ba").getGenericType() == byte[].class :
|
||||
"Type of Inner2.ba should be byte[]";
|
||||
assert
|
||||
in1.getField("sa").getGenericType() == short[].class :
|
||||
"Type of Inner2.sa should be short[]";
|
||||
assert
|
||||
in1.getField("ca").getGenericType() == char[].class :
|
||||
"Type of Inner2.xa should be char[]";
|
||||
assert
|
||||
in1.getField("ia").getGenericType() == int[].class :
|
||||
"Type of Inner2.ia should be int[]";
|
||||
assert
|
||||
in1.getField("la").getGenericType() == long[].class :
|
||||
"Type of Inner2.la should be long[]";
|
||||
assert
|
||||
in1.getField("fa").getGenericType() == float[].class :
|
||||
"Type of Inner2.fa should be float[]";
|
||||
assert
|
||||
in1.getField("da").getGenericType() == double[].class :
|
||||
"Type of Inner2.da should be double[]";
|
||||
}
|
||||
|
||||
|
||||
static void testInner3() {
|
||||
System.out.println("testing generic inner class 3");
|
||||
Class in1 = N1.Inner3.class;
|
||||
|
||||
TypeVariable[] tvs = in1.getTypeParameters();
|
||||
assert
|
||||
tvs.length == 3 :
|
||||
"N1.Inner2 should have three type parameters";
|
||||
}
|
||||
}
|
||||
147
test/jdk/java/lang/reflect/Generics/TestParameterizedType.java
Normal file
147
test/jdk/java/lang/reflect/Generics/TestParameterizedType.java
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* 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 5061485
|
||||
* @summary Test sematics of ParameterizedType.equals
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class TestParameterizedType {
|
||||
public <T> T genericMethod0() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> Set<T> genericMethod1() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> Set<T> genericMethod2() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <S> List<S> genericMethod3() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <X, Y> Map<X, Y> genericMethod4() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T[] genericMethod5() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T[] genericMethod6() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<? extends Cloneable> genericMethod7() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<? super Number> genericMethod8() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<?> genericMethod9() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
static List<Type> createTypes() throws Exception {
|
||||
List<Type> typeList = new ArrayList<Type>(3);
|
||||
String[] methodNames = {"genericMethod0",
|
||||
"genericMethod1",
|
||||
"genericMethod2",
|
||||
"genericMethod3",
|
||||
"genericMethod4",
|
||||
"genericMethod5",
|
||||
"genericMethod6",
|
||||
"genericMethod7",
|
||||
"genericMethod8",
|
||||
"genericMethod9",
|
||||
};
|
||||
|
||||
for(String s : methodNames) {
|
||||
Type t = TestParameterizedType.class.getDeclaredMethod(s).getGenericReturnType();
|
||||
// if (! (t instanceof ParameterizedType))
|
||||
// throw new RuntimeException("Unexpected kind of return type");
|
||||
typeList.add(t);
|
||||
}
|
||||
|
||||
return typeList;
|
||||
}
|
||||
|
||||
static boolean testReflexes(List<Type> typeList) {
|
||||
for(Type t : typeList) {
|
||||
if (! t.equals(t) ) {
|
||||
System.err.printf("Bad reflexes for%s %s%n", t, t.getClass());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void main(String[] argv) throws Exception {
|
||||
boolean failed = false;
|
||||
|
||||
List<Type> take1 = createTypes();
|
||||
List<Type> take2 = createTypes();
|
||||
|
||||
// Test reflexivity
|
||||
failed = failed | testReflexes(take1);
|
||||
failed = failed | testReflexes(take2);
|
||||
|
||||
for(int i = 0; i < take1.size(); i++) {
|
||||
Type type1 = take1.get(i);
|
||||
|
||||
for(int j = 0; j < take2.size(); j++) {
|
||||
Type type2 = take2.get(j);
|
||||
|
||||
if (i == j) {
|
||||
// corresponding types should be .equals
|
||||
if (!type1.equals(type2) ) {
|
||||
failed = true;
|
||||
System.err.printf("Unexpected inequality: [%d, %d] %n\t%s%n\t%s%n",
|
||||
i, j, type1, type2);
|
||||
}
|
||||
} else {
|
||||
// non-corresponding types should *not* be .equals
|
||||
if (type1.equals(type2) ) {
|
||||
failed = true;
|
||||
System.err.printf("Unexpected equality: [%d, %d] %n\t%s%n\t%s%n",
|
||||
i, j, type1, type2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (failed)
|
||||
throw new RuntimeException("Bad equality on ParameterizedTypes");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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 5041784
|
||||
* @summary Check that plain arrays like String[] are never represented as
|
||||
* GenericArrayType.
|
||||
* @author Eamonn McManus
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.GenericDeclaration;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class TestPlainArrayNotGeneric {
|
||||
public String[] m1(List<String> p1) {return null;}
|
||||
public List<String> m2(String[] p1) {return null;}
|
||||
public void m3(List<String> p1, String[] p2) {}
|
||||
public void m4(List<String[]> p1) {}
|
||||
public TestPlainArrayNotGeneric(List<String[]> p1) {}
|
||||
public TestPlainArrayNotGeneric(List<String> p1, String[] p2) {}
|
||||
|
||||
public <T extends List<String[]>> T m5(T p1) {return null;}
|
||||
public <T extends Object> T[] m6(T[] p1, List<T[]> p2) {return null;}
|
||||
|
||||
public List<? extends Object[]> m6(List<? extends Object[]> p1) {return null;}
|
||||
public <T extends List<? extends Object[]>> T m7(T[] p1) {return null;}
|
||||
public List<? super Object[]> m8(List<? super Object[]> p1) {return null;}
|
||||
public <T extends List<? super Object[]>> T[] m9(T[] p1) {return null;}
|
||||
|
||||
public static interface XMap extends Map<List<String[]>, String[]> {}
|
||||
public static interface YMap<K extends List<String[]>, V>
|
||||
extends Map<K[], V[]> {}
|
||||
|
||||
|
||||
private static String lastFailure;
|
||||
private static int failureCount;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
checkClass(TestPlainArrayNotGeneric.class);
|
||||
|
||||
if (failureCount == 0)
|
||||
System.out.println("TEST PASSED");
|
||||
else
|
||||
throw new Exception("TEST FAILED: Last failure: " + lastFailure);
|
||||
}
|
||||
|
||||
private static void checkClass(Class<?> c) throws Exception {
|
||||
Method[] methods = c.getMethods();
|
||||
for (Method m : methods) {
|
||||
check(m.getGenericReturnType(), "return type of method " + m);
|
||||
check(m.getGenericParameterTypes(), "parameter", "method " + m);
|
||||
check(m.getTypeParameters(), "type parameter", "method " + m);
|
||||
}
|
||||
|
||||
Constructor[] constructors = c.getConstructors();
|
||||
for (Constructor constr : constructors) {
|
||||
check(constr.getGenericParameterTypes(), "parameter",
|
||||
"constructor " + constr);
|
||||
check(constr.getTypeParameters(), "type parameter",
|
||||
"constructor " + constr);
|
||||
}
|
||||
|
||||
Class<?>[] inners = c.getDeclaredClasses();
|
||||
for (Class inner : inners)
|
||||
checkClass(inner);
|
||||
}
|
||||
|
||||
private static void check(Type[] types, String elementKind, String what) {
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
Type t = types[i];
|
||||
check(t, elementKind + " " + (i+1) + " of " + what);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Set<Type> checking = new HashSet<>();
|
||||
|
||||
private static void check(Type t, String what) {
|
||||
if (t == null || !checking.add(t))
|
||||
return;
|
||||
// Avoid infinite recursion. t can be null e.g. for superclass of Object.
|
||||
try {
|
||||
check2(t, what);
|
||||
} finally {
|
||||
checking.remove(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static void check2(Type t, String what) {
|
||||
if (t instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) t;
|
||||
check(pt.getActualTypeArguments(), "type argument", what);
|
||||
} else if (t instanceof TypeVariable) {
|
||||
TypeVariable<?> tv = (TypeVariable<?>) t;
|
||||
check(tv.getBounds(), "bound", what);
|
||||
GenericDeclaration gd = tv.getGenericDeclaration();
|
||||
if (gd instanceof Type)
|
||||
check((Type) gd, "declaration containing " + what);
|
||||
} else if (t instanceof WildcardType) {
|
||||
WildcardType wt = (WildcardType) t;
|
||||
check(wt.getLowerBounds(), "lower bound", "wildcard type in " + what);
|
||||
check(wt.getUpperBounds(), "upper bound", "wildcard type in " + what);
|
||||
} else if (t instanceof Class<?>) {
|
||||
Class<?> c = (Class<?>) t;
|
||||
check(c.getGenericInterfaces(), "superinterface", c.toString());
|
||||
check(c.getGenericSuperclass(), "superclass of " + c);
|
||||
check(c.getTypeParameters(), "type parameter", c.toString());
|
||||
} else if (t instanceof GenericArrayType) {
|
||||
GenericArrayType gat = (GenericArrayType) t;
|
||||
Type comp = gat.getGenericComponentType();
|
||||
if (comp instanceof Class) {
|
||||
fail("Type " + t + " uses GenericArrayType when plain " +
|
||||
"array would do, in " + what);
|
||||
} else
|
||||
check(comp, "component type of " + what);
|
||||
} else {
|
||||
fail("TEST BUG: mutant Type " + t + " (a " + t.getClass().getName() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
private static void fail(String why) {
|
||||
System.out.println("FAIL: " + why);
|
||||
lastFailure = why;
|
||||
failureCount++;
|
||||
}
|
||||
}
|
||||
135
test/jdk/java/lang/reflect/Generics/ThreadSafety.java
Normal file
135
test/jdk/java/lang/reflect/Generics/ThreadSafety.java
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright 2014 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8062771 8016236
|
||||
* @summary Test publication of Class objects via a data race
|
||||
* @run junit ThreadSafety
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* A test resulting from an attempt to repro this failure (in guice):
|
||||
*
|
||||
* java.lang.NullPointerException
|
||||
* at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125)
|
||||
* at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
|
||||
* at sun.reflect.generics.repository.ClassRepository.getSuperclass(ClassRepository.java:84)
|
||||
* at java.lang.Class.getGenericSuperclass(Class.java:692)
|
||||
* at com.google.inject.TypeLiteral.getSuperclassTypeParameter(TypeLiteral.java:99)
|
||||
* at com.google.inject.TypeLiteral.<init>(TypeLiteral.java:79)
|
||||
*
|
||||
* However, as one would expect with thread safety problems in reflection, these
|
||||
* are very hard to reproduce. This very test has never been observed to fail,
|
||||
* but a similar test has been observed to fail about once in 2000 executions
|
||||
* (about once every 6 CPU-hours), in jdk7 only. It appears to be fixed in jdk8+ by:
|
||||
*
|
||||
* 8016236: Class.getGenericInterfaces performance improvement.
|
||||
* (by making Class.genericInfo volatile)
|
||||
*/
|
||||
public class ThreadSafety {
|
||||
public static class EmptyClass {
|
||||
public static class EmptyGenericSuperclass<T> {}
|
||||
public static class EmptyGenericSubclass<T> extends EmptyGenericSuperclass<T> {}
|
||||
}
|
||||
|
||||
/** published via data race */
|
||||
private Class<?> racyClass = Object.class;
|
||||
|
||||
private Class<?> createNewEmptyGenericSubclassClass() throws Exception {
|
||||
String[] cpaths = System.getProperty("test.classes", ".")
|
||||
.split(File.pathSeparator);
|
||||
URL[] urls = new URL[cpaths.length];
|
||||
for (int i=0; i < cpaths.length; i++) {
|
||||
urls[i] = Paths.get(cpaths[i]).toUri().toURL();
|
||||
}
|
||||
URLClassLoader ucl = new URLClassLoader(urls, null);
|
||||
return Class.forName("ThreadSafety$EmptyClass$EmptyGenericSubclass", true, ucl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRacy_getGenericSuperclass() throws Exception {
|
||||
final int nThreads = 10;
|
||||
final int iterations = 30;
|
||||
final int timeout = 10;
|
||||
final CyclicBarrier newCycle = new CyclicBarrier(nThreads);
|
||||
final Callable<Void> task = new Callable<Void>() {
|
||||
public Void call() throws Exception {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
final int threadId;
|
||||
try {
|
||||
threadId = newCycle.await(timeout, SECONDS);
|
||||
} catch (BrokenBarrierException e) {
|
||||
return null;
|
||||
}
|
||||
for (int j = 0; j < iterations; j++) {
|
||||
// one thread publishes the class object via a data
|
||||
// race, for the other threads to consume.
|
||||
if (threadId == 0) {
|
||||
racyClass = createNewEmptyGenericSubclassClass();
|
||||
} else {
|
||||
racyClass.getGenericSuperclass();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}};
|
||||
|
||||
final ExecutorService pool = Executors.newFixedThreadPool(nThreads);
|
||||
try {
|
||||
for (Future<Void> future :
|
||||
pool.invokeAll(Collections.nCopies(nThreads, task))) {
|
||||
try {
|
||||
future.get(iterations * timeout, SECONDS);
|
||||
} catch (ExecutionException e) {
|
||||
// ignore "collateral damage"
|
||||
if (!(e.getCause() instanceof BrokenBarrierException)
|
||||
&&
|
||||
!(e.getCause() instanceof TimeoutException)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
pool.shutdownNow();
|
||||
assertTrue(pool.awaitTermination(2 * timeout, SECONDS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* 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 Signature attribute with any absent
|
||||
* class or interface (the string is of valid format)
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.classfile.components
|
||||
* @compile MalformedSignatureTest.java
|
||||
* @comment reuses Sample classes from MalformedSignatureTest
|
||||
* @run junit TypeNotPresentInSignatureTest
|
||||
*/
|
||||
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.ClassTransform;
|
||||
import java.lang.classfile.attribute.ExceptionsAttribute;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import jdk.internal.classfile.components.ClassRemapper;
|
||||
import jdk.test.lib.ByteCodeLoader;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class TypeNotPresentInSignatureTest {
|
||||
|
||||
static Class<?> sampleClass, sampleRecord;
|
||||
|
||||
@BeforeAll
|
||||
static void setup() throws Exception {
|
||||
var compiledDir = Path.of(System.getProperty("test.classes"));
|
||||
var cf = ClassFile.of();
|
||||
|
||||
// Transforms all references to RuntimeException to an absent class or
|
||||
// interface does.not.Exist. The signature string format is still valid.
|
||||
var reDesc = ClassDesc.of("java.lang.RuntimeException");
|
||||
var fix = ClassRemapper.of(Map.of(reDesc, ClassDesc.of("does.not.Exist")));
|
||||
var f2 = ClassTransform.transformingMethods((mb, me) -> {
|
||||
if (me instanceof ExceptionsAttribute) {
|
||||
mb.with(ExceptionsAttribute.ofSymbols(reDesc));
|
||||
} else {
|
||||
mb.with(me);
|
||||
}
|
||||
});
|
||||
|
||||
var plainBytes = cf.transformClass(cf.parse(compiledDir.resolve("SampleClass.class")), fix);
|
||||
plainBytes = cf.transformClass(cf.parse(plainBytes), f2);
|
||||
sampleClass = ByteCodeLoader.load("SampleClass", plainBytes);
|
||||
var recordBytes = cf.transformClass(cf.parse(compiledDir.resolve("SampleRecord.class")), fix);
|
||||
recordBytes = cf.transformClass(cf.parse(recordBytes), f2);
|
||||
sampleRecord = ByteCodeLoader.load("SampleRecord", recordBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the reflective generic inspection of a Class with missing class
|
||||
* or interface throws TypeNotPresentException while the non-generic
|
||||
* inspection is fine.
|
||||
*/
|
||||
@Test
|
||||
void testClass() {
|
||||
assertEquals(ArrayList.class, sampleClass.getSuperclass());
|
||||
assertArrayEquals(new Class<?>[] {Predicate.class}, sampleClass.getInterfaces());
|
||||
var ex = assertThrows(TypeNotPresentException.class, sampleClass::getGenericSuperclass);
|
||||
assertEquals("does.not.Exist", ex.typeName());
|
||||
ex = assertThrows(TypeNotPresentException.class, sampleClass::getGenericInterfaces);
|
||||
assertEquals("does.not.Exist", ex.typeName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the reflective generic inspection of a Field with missing class
|
||||
* or interface throws TypeNotPresentException while the non-generic
|
||||
* inspection is fine.
|
||||
*/
|
||||
@Test
|
||||
void testField() throws ReflectiveOperationException {
|
||||
var field = sampleClass.getDeclaredField("field");
|
||||
assertEquals(Optional.class, field.getType());
|
||||
var ex = assertThrows(TypeNotPresentException.class, field::getGenericType);
|
||||
assertEquals("does.not.Exist", ex.typeName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the reflective generic inspection of a Constructor with missing class
|
||||
* or interface throws TypeNotPresentException while the non-generic
|
||||
* inspection is fine.
|
||||
*/
|
||||
@Test
|
||||
void testConstructor() throws ReflectiveOperationException {
|
||||
var constructor = sampleClass.getDeclaredConstructor(Optional.class);
|
||||
assertArrayEquals(new Class<?>[] {Optional.class}, constructor.getParameterTypes());
|
||||
assertArrayEquals(new Class<?>[] {RuntimeException.class}, constructor.getExceptionTypes());
|
||||
var ex = assertThrows(TypeNotPresentException.class, constructor::getGenericParameterTypes);
|
||||
assertEquals("does.not.Exist", ex.typeName());
|
||||
var typeVar = (TypeVariable<?>) constructor.getGenericExceptionTypes()[0];
|
||||
ex = assertThrows(TypeNotPresentException.class, typeVar::getBounds);
|
||||
assertEquals("does.not.Exist", ex.typeName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the reflective generic inspection of a Method with missing class
|
||||
* or interface throws TypeNotPresentException while the non-generic
|
||||
* inspection is fine.
|
||||
*/
|
||||
@Test
|
||||
void testMethod() throws ReflectiveOperationException {
|
||||
var method = sampleClass.getDeclaredMethod("method", Optional.class);
|
||||
assertEquals(Optional.class, method.getReturnType());
|
||||
assertArrayEquals(new Class<?>[] {Optional.class}, method.getParameterTypes());
|
||||
assertArrayEquals(new Class<?>[] {RuntimeException.class}, method.getExceptionTypes());
|
||||
var ex = assertThrows(TypeNotPresentException.class, method::getGenericReturnType);
|
||||
assertEquals("does.not.Exist", ex.typeName());
|
||||
ex = assertThrows(TypeNotPresentException.class, method::getGenericParameterTypes);
|
||||
assertEquals("does.not.Exist", ex.typeName());
|
||||
var typeVar = (TypeVariable<?>) method.getGenericExceptionTypes()[0];
|
||||
ex = assertThrows(TypeNotPresentException.class, typeVar::getBounds);
|
||||
assertEquals("does.not.Exist", ex.typeName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the reflective generic inspection of a RecordComponent with missing class
|
||||
* or interface throws TypeNotPresentException while the non-generic
|
||||
* inspection is fine.
|
||||
*/
|
||||
@Test
|
||||
void testRecordComponent() {
|
||||
var rcs = sampleRecord.getRecordComponents();
|
||||
assertNotNull(rcs);
|
||||
assertEquals(1, rcs.length);
|
||||
var rc = rcs[0];
|
||||
assertNotNull(rc);
|
||||
|
||||
assertEquals(Optional.class, rc.getType());
|
||||
assertEquals("Ljava/util/Optional<Ldoes/not/Exist;>;", rc.getGenericSignature());
|
||||
var ex = assertThrows(TypeNotPresentException.class, rc::getGenericType);
|
||||
assertEquals("does.not.Exist", ex.typeName());
|
||||
}
|
||||
}
|
||||
45
test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java
Normal file
45
test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 4981727
|
||||
* @summary
|
||||
*/
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class exceptionCauseTest {
|
||||
public static void main(String args[]) {
|
||||
Throwable cause = new Throwable("because");
|
||||
Throwable par = new Throwable(cause);
|
||||
TypeNotPresentException cnp = new TypeNotPresentException("test", par);
|
||||
|
||||
try {
|
||||
throw cnp;
|
||||
} catch (TypeNotPresentException e) {
|
||||
if (par != e.getCause() )
|
||||
throw new RuntimeException("Unexpected value of cause.");
|
||||
}
|
||||
}
|
||||
}
|
||||
64
test/jdk/java/lang/reflect/Generics/getAnnotationTest.java
Normal file
64
test/jdk/java/lang/reflect/Generics/getAnnotationTest.java
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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 4979440
|
||||
* @summary Test for signature parsing corner case
|
||||
*/
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/*
|
||||
* Make sure:
|
||||
* 1. getAnnotation can be called directly
|
||||
* 2. getAnnotation can be called reflectively
|
||||
* 3. generic information methods on the Method object for
|
||||
* getAnnotation can be called
|
||||
*/
|
||||
|
||||
public class getAnnotationTest {
|
||||
public static void main (String[] args) throws Throwable {
|
||||
// Base level
|
||||
Class c = Class.forName("java.lang.annotation.Retention");
|
||||
Annotation result = c.getAnnotation(Retention.class);
|
||||
// System.out.println("Base result:" + result);
|
||||
|
||||
// Meta level, invoke Class.getAnnotation reflectively...
|
||||
Class meta_c = c.getClass();
|
||||
Method meta_getAnnotation = meta_c.getMethod("getAnnotation",
|
||||
(Retention.class).getClass());
|
||||
|
||||
Object meta_result = meta_getAnnotation.invoke(c, Retention.class);
|
||||
// System.out.println("Meta result:" + meta_result);
|
||||
|
||||
if (!meta_result.equals(result)) {
|
||||
throw new RuntimeException("Base and meta results are not equal.");
|
||||
}
|
||||
|
||||
meta_getAnnotation.getGenericExceptionTypes();
|
||||
meta_getAnnotation.getGenericParameterTypes();
|
||||
meta_getAnnotation.getGenericReturnType();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue