Skip to content

Commit 1d070a3

Browse files
raphwliach
authored andcommitted
8337302: Undefined type variable results in null
Reviewed-by: liach
1 parent aeba1ea commit 1d070a3

File tree

3 files changed

+86
-12
lines changed

3 files changed

+86
-12
lines changed

src/java.base/share/classes/java/lang/TypeNotPresentException.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -28,9 +28,9 @@
2828
/**
2929
* Thrown when an application tries to access a type using a string
3030
* representing the type's name, but no definition for the type with
31-
* the specified name can be found. This exception differs from
32-
* {@link ClassNotFoundException} in that {@code ClassNotFoundException} is a
33-
* checked exception, whereas this exception is unchecked.
31+
* the specified name can be found. This exception differs from
32+
* {@link ClassNotFoundException} in that {@code ClassNotFoundException}
33+
* is a checked exception, whereas this exception is unchecked.
3434
*
3535
* <p>Note that this exception may be used when undefined type variables
3636
* are accessed as well as when types (e.g., classes, interfaces or
@@ -48,15 +48,15 @@ public class TypeNotPresentException extends RuntimeException {
4848
private static final long serialVersionUID = -5101214195716534496L;
4949

5050
/**
51-
* The type name.
51+
* The type name or the name of a type variable.
5252
*/
5353
private String typeName;
5454

5555
/**
56-
* Constructs a {@code TypeNotPresentException} for the named type
57-
* with the specified cause.
56+
* Constructs a {@code TypeNotPresentException} for the named type or
57+
* type variable with the specified cause.
5858
*
59-
* @param typeName the fully qualified name of the unavailable type
59+
* @param typeName the fully qualified name of the unavailable type or type variable
6060
* @param cause the exception that was thrown when the system attempted to
6161
* load the named type, or {@code null} if unavailable or inapplicable
6262
*/
@@ -66,9 +66,9 @@ public TypeNotPresentException(String typeName, Throwable cause) {
6666
}
6767

6868
/**
69-
* Returns the fully qualified name of the unavailable type.
69+
* Returns the fully qualified name of the unavailable type or type variable name.
7070
*
71-
* @return the fully qualified name of the unavailable type
71+
* @return the fully qualified name of the unavailable type or type variable name
7272
*/
7373
public String typeName() { return typeName;}
7474
}

src/java.base/share/classes/sun/reflect/generics/factory/CoreReflectionFactory.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -106,7 +106,11 @@ public ParameterizedType makeParameterizedType(Type declaration,
106106
}
107107

108108
public TypeVariable<?> findTypeVariable(String name){
109-
return getScope().lookup(name);
109+
TypeVariable<?> variable = getScope().lookup(name);
110+
if (variable == null) {
111+
throw new TypeNotPresentException(name, null);
112+
}
113+
return variable;
110114
}
111115

112116
public Type makeNamedType(String name){
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @library /test/lib
27+
* @bug 8337302
28+
* @enablePreview
29+
* @summary Tests that an exception is thrown if a type variable is not declared
30+
*/
31+
32+
import jdk.test.lib.ByteCodeLoader;
33+
34+
import java.lang.classfile.ClassFile;
35+
import java.lang.classfile.Signature;
36+
import java.lang.classfile.attribute.SignatureAttribute;
37+
import java.lang.constant.ClassDesc;
38+
import java.lang.reflect.AccessFlag;
39+
import java.lang.reflect.Type;
40+
41+
public class TestMissingTypeVariable {
42+
43+
public static void main(String[] args) throws Exception {
44+
ClassFile cf = ClassFile.of();
45+
byte[] bytes = cf.build(
46+
ClassDesc.of("sample.MissingVariable"),
47+
classBuilder -> {
48+
classBuilder.withSuperclass(ClassDesc.of("java.lang.Object"));
49+
classBuilder.withFlags(AccessFlag.PUBLIC);
50+
classBuilder.withField("f",
51+
ClassDesc.of("java.lang.Object"),
52+
fieldBuilder -> fieldBuilder.withFlags(AccessFlag.PUBLIC).with(SignatureAttribute.of(Signature.parseFrom("TA;"))));
53+
});
54+
/*
55+
package sample;
56+
public class MissingVariable {
57+
public A f; // undeclared type variable
58+
}
59+
*/
60+
Class<?> missing = ByteCodeLoader.load("sample.MissingVariable", bytes);
61+
try {
62+
Type type = missing.getField("f").getGenericType();
63+
throw new IllegalStateException("Expected TypeNotPresentException but got: " + type);
64+
} catch (TypeNotPresentException e) {
65+
if (!"A".equals(e.typeName())) {
66+
throw new IllegalStateException("Unexpected name: " + e.typeName());
67+
}
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)