A DESCRIPTION OF THE PROBLEM :
Note: This only seems to affect Java 11 (and possibly other versions), Java 17 is apparently not affected.
Preconditions:
- a generic method M of a local class ...
- contains a lambda expression ...
- which creates an anonymous class C of a generic class ...
- which captures a type variable from M
In that case reflection erroneously returns `null` as type argument for C.
If any of the above is changed, e.g. not using a lambda, or not using a local class, then it looks like this cannot be reproduced.
Have reported this as compiler bug because compiling with JDK 11 and running with JDK 17 still seems to reproduce this (whereas compiling and running using only JDK 17 does not). But maybe this is actually a combination of a compiler and a reflection library bug.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the code provided below using `java Test.java`
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
It should print: "Found expected type"
ACTUAL -
Exception in thread "main" java.lang.AssertionError: Unexpected type: null
---------- BEGIN SOURCE ----------
import java.lang.reflect.*;
class Test {
static class Capturing<T> {
protected Capturing() {
ParameterizedType paramT = (ParameterizedType) getClass().getGenericSuperclass();
Type t = paramT.getActualTypeArguments()[0];
if (t instanceof TypeVariable) {
System.out.println("Found expected type");
} else {
throw new AssertionError("Unexpected type: " + t);
}
}
}
static void run(Runnable r) {
r.run();
}
public static <T> void main(String... args) {
class Local {
<M> void runTest() {
run(() -> new Capturing<M>() {});
}
}
new Local().runTest();
}
}
---------- END SOURCE ----------
Note: This only seems to affect Java 11 (and possibly other versions), Java 17 is apparently not affected.
Preconditions:
- a generic method M of a local class ...
- contains a lambda expression ...
- which creates an anonymous class C of a generic class ...
- which captures a type variable from M
In that case reflection erroneously returns `null` as type argument for C.
If any of the above is changed, e.g. not using a lambda, or not using a local class, then it looks like this cannot be reproduced.
Have reported this as compiler bug because compiling with JDK 11 and running with JDK 17 still seems to reproduce this (whereas compiling and running using only JDK 17 does not). But maybe this is actually a combination of a compiler and a reflection library bug.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the code provided below using `java Test.java`
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
It should print: "Found expected type"
ACTUAL -
Exception in thread "main" java.lang.AssertionError: Unexpected type: null
---------- BEGIN SOURCE ----------
import java.lang.reflect.*;
class Test {
static class Capturing<T> {
protected Capturing() {
ParameterizedType paramT = (ParameterizedType) getClass().getGenericSuperclass();
Type t = paramT.getActualTypeArguments()[0];
if (t instanceof TypeVariable) {
System.out.println("Found expected type");
} else {
throw new AssertionError("Unexpected type: " + t);
}
}
}
static void run(Runnable r) {
r.run();
}
public static <T> void main(String... args) {
class Local {
<M> void runTest() {
run(() -> new Capturing<M>() {});
}
}
new Local().runTest();
}
}
---------- END SOURCE ----------