Inverse annotation inheritance issue with generic interfaces
Remi Forax
forax at univ-mlv.fr
Sat Dec 5 19:46:53 UTC 2015
Hi Lukas,
First, reflection do not provide runtime objects for Java the language constructions but for VM class format constructions.
And sometimes, the Java view and the bytecode view are slightly different.
What you are seeing in your example is the introduction by the compiler of a bridge method (you can google it for more info), that is generated by the compiler in order to support the case of a class that implements a generic interface with a type parameter/type argument with a different bound.
The OpenJDK7 compiler you use has a bug because a bridge method should not have annotation attached to it,
you can easily fix the issue by filter out the method that are marked as bridge method [1].
cheers,
Rémi
[1] http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#isBridge--
----- Mail original -----
> De: "Lukas Magel" <luke-mail at online.de>
> À: compiler-dev at openjdk.java.net
> Envoyé: Jeudi 12 Novembre 2015 01:55:37
> Objet: Inverse annotation inheritance issue with generic interfaces
>
> Hello,
>
> I am currently working on a JAVA EE web project and have been
> experiencing a compiler behavior which I don't know how to interpret.
>
> In our code we define interfaces like the following:
>
> public interface SampleInterface<T extends A> {
>
> public void sampleMethod(T t);
>
> }
>
> as well as an implementing class:
>
> public class Main implements SampleInterface<B> {
>
> @SampleAnnotation
> public void sampleMethod(B t) {
>
> }
> }
>
> and the corresponding annotation:
>
> @Retention(RetentionPolicy.RUNTIME)
> @Target(ElementType.METHOD)
> public @interface SampleAnnotation {
>
> }
>
> Where Class B extends A. All classes are compiled using the OpenJDK7
> compiler. If I use Reflection to retrieve all methods of the Main class
> at runtime and print each method with its annotations I get the
> following list of methods:
>
> class Main
>
> public void Main.sampleMethod(A)
> @SampleAnnotation()
>
> public void Main.sampleMethod(B)
> @SampleAnnotation()
>
> The compiler will assign the annotation to the method declaration of the
> interface although the annotation is only declared in the implementing
> class. I cannot reproduce this behavior with the Oracle Java Compiler or
> the Eclipse JDT Compiler. If I compile the example with one of the two
> compilers the resulting program will yield the following result:
>
> class annotation.Main
>
> public void annotation.Main.sampleMethod(annotation.A)
>
> public void annotation.Main.sampleMethod(annotation.B)
> @annotation.SampleAnnotation()
>
> The JRE type (Oracle, OpenJDK) that the program is executed with has no
> influence on the result.
>
> My actual question is whether this behavior is intended or not because
> it causes quite some issues with our JAXRS REST implementations. All
> REST classes each implement an interface like the one above and are
> annotated with multiple annotations to allow the container to identify
> endpoints at runtime. The JAXRS framework uses reflection to determine
> possible method candidates at runtime and will happily accept both the
> generic and the special method since both of the carry the annotations.
>
> I can also provide an example project if necessary.
>
> Thanks,
> Lukas
>
More information about the compiler-dev
mailing list