Inverse annotation inheritance issue with generic interfaces

Lukas Magel luke-mail at online.de
Mon Nov 23 13:35:33 UTC 2015


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 OpenJDK 
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 Main.sampleMethod(A)

public void Main.sampleMethod(B)
@SampleAnnotation()

The JRE type (Oracle, OpenJDK) that the program is executed with has no 
influence on the result.

This behavior is reproducible with the following constellations:
JDK            Operating System        Hardware
1.7.0_85    Ubuntu 14.04.03         x86-64
1.7.0_91    Arch Linux                   x86-64
1.8.0_66    Arch Linux                   x86-64

It is NOT reproducible with the following constellation:
1.7.0_51    Ubuntu 13.04              x86-64

My actual question is whether this behavior is intended or not. It 
causes quite some issues with our Jax-RS 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 Jax-RS framework uses reflection to determine possible 
method candidates at runtime and will happily accept both the generic 
and the special method since both of them carry the annotations.

I can also provide an example project if necessary.

Thanks,
Lukas


More information about the compiler-dev mailing list