-
Bug
-
Resolution: Cannot Reproduce
-
P4
-
8, 9
-
generic
-
generic
FULL PRODUCT VERSION :
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux gsmet.redhat.lyon 4.9.13-200.fc25.x86_64 #1 SMP Mon Feb 27 16:48:42 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
For a parameterized inner class, the annotation defined on the type parameter are simply ignored and it is not possible to get them via reflection.
It works perfectly fine if the parameterized class is defined in its own file.
This bug has an easy workaround (use an external class instead of an inner class) but is really annoying as it's very hard for the user to understand why it does not work.
Note that the issue is also reproducible with the latest JDK 9 EA build (164):
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+164)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+164, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
mkdir -p src/main/java/org/hibernate/jdk/innerclassannotationbug
cat > src/main/java/org/hibernate/jdk/innerclassannotationbug/ExternalClass.java <<EOL
package org.hibernate.jdk.innerclassannotationbug;
public class ExternalClass<T> {
}
EOL
cat > src/main/java/org/hibernate/jdk/innerclassannotationbug/MyAnnotation.java <<EOL
package org.hibernate.jdk.innerclassannotationbug;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@Documented
public @interface MyAnnotation {
}
EOL
cat > src/main/java/org/hibernate/jdk/innerclassannotationbug/AnnotationNotFoundTest.java <<EOL
package org.hibernate.jdk.innerclassannotationbug;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Field;
import java.util.List;
public class AnnotationNotFoundTest {
private final List<InnerClass<@MyAnnotation String>> listOfGenericInnerType = null;
private final List<ExternalClass<@MyAnnotation String>> listOfGenericExternalType = null;
public static void main(String[] args) throws Exception {
checkAnnotationIsPresent( "listOfGenericExternalType" );
checkAnnotationIsPresent( "listOfGenericInnerType" );
}
private static void checkAnnotationIsPresent(String fieldName) throws Exception {
Field field = AnnotationNotFoundTest.class.getDeclaredField( fieldName );
AnnotatedParameterizedType fieldType = (AnnotatedParameterizedType) field.getAnnotatedType();
AnnotatedParameterizedType listElementType = (AnnotatedParameterizedType) fieldType.getAnnotatedActualTypeArguments()[0];
AnnotatedType[] elementTypeTypeArguments = listElementType.getAnnotatedActualTypeArguments();
if ( elementTypeTypeArguments[0].isAnnotationPresent( MyAnnotation.class ) ) {
System.out.println( "Success: annotation found for " + fieldName );
}
else {
System.out.println( "ERROR: annotation not found for " + fieldName );
}
}
private static class InnerClass<T> {
}
}
EOL
mkdir target
javac -d target/ src/main/java/org/hibernate/jdk/innerclassannotationbug/*.java
java -cp target org.hibernate.jdk.innerclassannotationbug.AnnotationNotFoundTest
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Success: annotation found for listOfGenericExternalType
Success: annotation found for listOfGenericInnerType
ACTUAL -
Success: annotation found for listOfGenericExternalType
ERROR: annotation not found for listOfGenericInnerType
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
See "Steps to Reproduce"
---------- END SOURCE ----------
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux gsmet.redhat.lyon 4.9.13-200.fc25.x86_64 #1 SMP Mon Feb 27 16:48:42 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
For a parameterized inner class, the annotation defined on the type parameter are simply ignored and it is not possible to get them via reflection.
It works perfectly fine if the parameterized class is defined in its own file.
This bug has an easy workaround (use an external class instead of an inner class) but is really annoying as it's very hard for the user to understand why it does not work.
Note that the issue is also reproducible with the latest JDK 9 EA build (164):
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+164)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+164, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
mkdir -p src/main/java/org/hibernate/jdk/innerclassannotationbug
cat > src/main/java/org/hibernate/jdk/innerclassannotationbug/ExternalClass.java <<EOL
package org.hibernate.jdk.innerclassannotationbug;
public class ExternalClass<T> {
}
EOL
cat > src/main/java/org/hibernate/jdk/innerclassannotationbug/MyAnnotation.java <<EOL
package org.hibernate.jdk.innerclassannotationbug;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@Documented
public @interface MyAnnotation {
}
EOL
cat > src/main/java/org/hibernate/jdk/innerclassannotationbug/AnnotationNotFoundTest.java <<EOL
package org.hibernate.jdk.innerclassannotationbug;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Field;
import java.util.List;
public class AnnotationNotFoundTest {
private final List<InnerClass<@MyAnnotation String>> listOfGenericInnerType = null;
private final List<ExternalClass<@MyAnnotation String>> listOfGenericExternalType = null;
public static void main(String[] args) throws Exception {
checkAnnotationIsPresent( "listOfGenericExternalType" );
checkAnnotationIsPresent( "listOfGenericInnerType" );
}
private static void checkAnnotationIsPresent(String fieldName) throws Exception {
Field field = AnnotationNotFoundTest.class.getDeclaredField( fieldName );
AnnotatedParameterizedType fieldType = (AnnotatedParameterizedType) field.getAnnotatedType();
AnnotatedParameterizedType listElementType = (AnnotatedParameterizedType) fieldType.getAnnotatedActualTypeArguments()[0];
AnnotatedType[] elementTypeTypeArguments = listElementType.getAnnotatedActualTypeArguments();
if ( elementTypeTypeArguments[0].isAnnotationPresent( MyAnnotation.class ) ) {
System.out.println( "Success: annotation found for " + fieldName );
}
else {
System.out.println( "ERROR: annotation not found for " + fieldName );
}
}
private static class InnerClass<T> {
}
}
EOL
mkdir target
javac -d target/ src/main/java/org/hibernate/jdk/innerclassannotationbug/*.java
java -cp target org.hibernate.jdk.innerclassannotationbug.AnnotationNotFoundTest
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Success: annotation found for listOfGenericExternalType
Success: annotation found for listOfGenericInnerType
ACTUAL -
Success: annotation found for listOfGenericExternalType
ERROR: annotation not found for listOfGenericInnerType
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
See "Steps to Reproduce"
---------- END SOURCE ----------