Inverse annotation inheritance issue with generic interfaces
Alex Buckley
alex.buckley at oracle.com
Tue Nov 24 00:09:44 UTC 2015
On 11/23/2015 1:50 PM, Maurizio Cimadamore wrote:
> 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.
Hard to confirm from the javadoc (as usual), but I imagine you're right.
> 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.
I guess the fix was to emit the RuntimeVisibleAnnotations attribute for
the bridge method sampleMethod(A) -- the change from non-emission (in
1.7.0_51) to emission (in 1.7.0_85) is visible in Lukas' javap output.
Ah, and here's the thread from exactly two years ago:
Annotations on return-overridden methods also end up on bridge methods
http://mail.openjdk.java.net/pipermail/compiler-dev/2013-November/008147.html
So Lukas, the behavior is intended. See
https://bugs.openjdk.java.net/browse/JDK-6695379 for more.
Alex
> 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