Inverse annotation inheritance issue with generic interfaces
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Nov 23 21:50:15 UTC 2015
On 23/11/15 20:41, Alex Buckley wrote:
> Enumerating the methods of Main.class shouldn't reveal
> sampleMethod(A), since sampleMethod(B) overrides it. I suspect a
> bridge method bug is being tickled, probably in Core Reflection rather
> than javac.
Not sure what you mean here - as far as I recall, reflection always
listed all methods (bridges included) in a given class.
I think what is being observed is this:
https://bugs.openjdk.java.net/browse/JDK-669537
Which I think was a legitimate fix - the callee probably wants to be
able to retrieve all applicable annotations, regardless of whether it
accidentally hit the bridge doing the reflective lookup.
Maurizio
> What is the full javap output for Main.class as compiled with Oracle
> JDK 1.7.0_51 versus Oracle JDK 1.7.0_85 ? (Plain text inline, please.)
>
> Alex
>
> On 11/23/2015 5:35 AM, Lukas Magel wrote:
>> 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