-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
17, 18, 19
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
The return result of Constructor.getAnnotatedParameterTypes() for enum constructors are wrong, that it maps annotations on formal parameters to descriptor-based parameters without an offset of 2. The annotation attribute in the class file seems correct, and this issue happens either when -parameter flag of javac is set or not.
The non-type-annotation equivalent for enum was fixed inJDK-8263763, and the type annotation inner class equivalent was fixed in JDK-8074977.
May be feasible to unify the offset detection mechanism for both type annotations in TypeAnnotationParser and regular annotations in Executable.handleParameterNumberMismatch, or even that for signatures for formal parameters. Currently there are 3 different systems for mapping them, which is costly for maintenance and is a blind spot in Java Language and JVM specifications.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Write an enum constructor that use TYPE annotations on its parameters. Observe that the type annotations
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The annotated type of the cmp argument should be @TypeAnno Comparator when inspected by reflection; when javac compiles this class with -parameters flag, it should be presented as @Comparator<@TypeAnno String>. The annotated type of the synthetic $enum$name argument (param 0) should be String.
ACTUAL -
The annotated type of cmp is Comparator or Comparator<String> (with javac -parameters flag); the annotated type of $enum$name is @TypeAnno String.
---------- BEGIN SOURCE ----------
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
enum EnumCtor {
;
EnumCtor(@TypeAnno Comparator<@TypeAnno String> cmp) {} // relevant content
public static void main(String... args) throws Throwable {
inspect(EnumCtor.class.getDeclaredConstructor(String.class, Integer.TYPE, Comparator.class));
}
static void inspect(Executable ctor) {
var params = ctor.getParameters();
System.out.println("Params:\n" + Arrays.toString(params));
System.out.println("Param types:\n" + Arrays.toString(ctor.getParameterTypes()));
System.out.println("Generic Params:\n" + Arrays.toString(ctor.getGenericParameterTypes()));
System.out.println("Annotated Params:\n" + Arrays.toString(ctor.getAnnotatedParameterTypes()));
System.out.println("Receiver:\n" + ctor.getAnnotatedReceiverType());
for (int i = 0; i < params.length; i++) {
var p = params[i];
System.out.println("Param " + i + ":\n" + p.getType() + ", " + p.getParameterizedType() + ", " + p.getAnnotatedType());
}
System.out.println();
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface TypeAnno {}
---------- END SOURCE ----------
FREQUENCY : always
The return result of Constructor.getAnnotatedParameterTypes() for enum constructors are wrong, that it maps annotations on formal parameters to descriptor-based parameters without an offset of 2. The annotation attribute in the class file seems correct, and this issue happens either when -parameter flag of javac is set or not.
The non-type-annotation equivalent for enum was fixed in
May be feasible to unify the offset detection mechanism for both type annotations in TypeAnnotationParser and regular annotations in Executable.handleParameterNumberMismatch, or even that for signatures for formal parameters. Currently there are 3 different systems for mapping them, which is costly for maintenance and is a blind spot in Java Language and JVM specifications.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Write an enum constructor that use TYPE annotations on its parameters. Observe that the type annotations
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The annotated type of the cmp argument should be @TypeAnno Comparator when inspected by reflection; when javac compiles this class with -parameters flag, it should be presented as @Comparator<@TypeAnno String>. The annotated type of the synthetic $enum$name argument (param 0) should be String.
ACTUAL -
The annotated type of cmp is Comparator or Comparator<String> (with javac -parameters flag); the annotated type of $enum$name is @TypeAnno String.
---------- BEGIN SOURCE ----------
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
enum EnumCtor {
;
EnumCtor(@TypeAnno Comparator<@TypeAnno String> cmp) {} // relevant content
public static void main(String... args) throws Throwable {
inspect(EnumCtor.class.getDeclaredConstructor(String.class, Integer.TYPE, Comparator.class));
}
static void inspect(Executable ctor) {
var params = ctor.getParameters();
System.out.println("Params:\n" + Arrays.toString(params));
System.out.println("Param types:\n" + Arrays.toString(ctor.getParameterTypes()));
System.out.println("Generic Params:\n" + Arrays.toString(ctor.getGenericParameterTypes()));
System.out.println("Annotated Params:\n" + Arrays.toString(ctor.getAnnotatedParameterTypes()));
System.out.println("Receiver:\n" + ctor.getAnnotatedReceiverType());
for (int i = 0; i < params.length; i++) {
var p = params[i];
System.out.println("Param " + i + ":\n" + p.getType() + ", " + p.getParameterizedType() + ", " + p.getAnnotatedType());
}
System.out.println();
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface TypeAnno {}
---------- END SOURCE ----------
FREQUENCY : always
- duplicates
-
JDK-8292275 javac does not emit SYNTHETIC and MANDATED flags for parameters by default
-
- Resolved
-
- relates to
-
JDK-8180892 Correct handling of annotations on parameters
-
- Open
-
-
JDK-8263763 Synthetic constructor parameters of enum are not considered for annotation indices
-
- Resolved
-
-
JDK-8074977 Constructor.getAnnotatedParameterTypes returns wrong value
-
- Closed
-