Bug in encoding type annotations for supertype_targets

Joel Borggrén-Franck joel.borggren.franck at gmail.com
Sun Jan 31 16:37:41 UTC 2016


So when debugging this in javac I realized I'm probably wrong, and
this looks like a reflection issue once again.

In both "erroneous" cases above the class or the interface is
statically nested, so there is only one type where the annotation can
appear (the innermost type). I checked a similar case on fields,

public class Outer {
    public static class Inner {
        Outer . @TA Outer foo;
    }
}

and javac omits the type_path here as well. I'm not sure this was a
conscious choice, but due to how javac treats statically nested
classes I think this will be consistent across the board. This means
I'll have to sort out the nesting on the reflective side.

What do you think?

cheers
/Joel

On Thu, Jan 28, 2016 at 9:12 PM, Alex Buckley <alex.buckley at oracle.com> wrote:
> Yes, we are agreeing that i) target_info (in particular, the
> supertype_target variant) is likely emitted correctly, and ii) target_path
> is not.
>
> It also seems that javap is printing "type_index=..." for the target_info
> item (not target_path as I said before).
>
> Alex
>
>
> On 1/28/2016 12:05 PM, Joel Borggrén-Franck wrote:
>>
>> Hi Alex,
>>
>> Actually I suspect the target_info is correct, a supertype_target with
>> a supertype_index of 65535 for the class cases but read into a signed
>> char, and 0 for the 0:th interface. This isn't the type_index entry
>> later in type_annotation structure, Javap just has a non-standard
>> notation (another bug perhaps?)
>>
>> Created: https://bugs.openjdk.java.net/browse/JDK-8148504
>>
>> cheers
>> /Joel
>>
>> On Thu, Jan 28, 2016 at 8:35 PM, Alex Buckley <alex.buckley at oracle.com>
>> wrote:
>>>
>>> Hi Joel,
>>>
>>> On 1/28/2016 10:45 AM, Joel Borggrén-Franck wrote:
>>>>
>>>>
>>>> While working on the core reflection code for type annotation I
>>>> discovered what I believe is a javac bug. It looks like javac omits
>>>> the type_path structure for nested types in supertype and implemets
>>>> targets. In the example below, when looking at GenericSub in javap I
>>>> get this encoding of @Foo:
>>>>
>>>> RuntimeVisibleTypeAnnotations:
>>>>     0: #18(): CLASS_EXTENDS, type_index=-1, location=[TYPE_ARGUMENT(0)]
>>>>
>>>> as expected, but when looking at either Impl or SubInner I get:
>>>>
>>>> RuntimeVisibleTypeAnnotations:
>>>>     0: #15(): CLASS_EXTENDS, type_index=0
>>>>
>>>> or
>>>>
>>>> RuntimeVisibleTypeAnnotations:
>>>>     0: #14(): CLASS_EXTENDS, type_index=-1
>>>>
>>>> Note the missing type_path (location in javap) for the nesting, which
>>>> I think table Table 4.7.20.2-E in the vm spec implies.
>>>>
>>>> I can file a bug if you want me to.
>>>
>>>
>>>
>>> I agree that the "Outer . @Foo Inner"-style terms are legal, and should
>>> have
>>> a target_path item generated.
>>>
>>> To be precise, the supertype_target item belongs to the target_info item,
>>> not the target_path item. supertype_target encodes which type is of
>>> interest
>>> among the one or more types specified after 'extends'/'implements'. All
>>> your
>>> sample programs have exactly one type in their 'extends'/'implements'
>>> clauses, so I'd be fairly confident that supertype_target is correct.
>>> What
>>> is more likely to be wrong is (as you say) the target_path item which
>>> encodes the "structural" location of a type annotation within a
>>> nested/parameterized/array type.
>>>
>>> The type_index items are surprising too. type_index is not about the
>>> location of a type annotation, but about the annotation itself ("@Foo").
>>> It
>>> encodes the constant pool entry which gives the annotation's own type. 0
>>> and
>>> -1 are bad answers for that. I suspect javap is actually finding
>>> target_path
>>> items (possibly ill-formed) and showing them as type_index.
>>>
>>> So yes, please file a bug.
>>>
>>> Alex
>>>
>>>
>>>> cheers
>>>> /Joel
>>>>
>>>> --- 8< ---
>>>>
>>>> import java.lang.annotation.*;
>>>> import java.util.*;
>>>> import java.lang.reflect.*;
>>>>
>>>> /*
>>>>    * @test
>>>>    */
>>>> public class LostTypePath {}
>>>>
>>>> class Super {}
>>>> class Sub extends @Foo Super {}
>>>>
>>>> class Generic<A> {}
>>>> class GenericSub<B> extends Generic<@Foo B> {}
>>>>
>>>> class Outer { public static class Inner {}}
>>>> class SubInner extends Outer . @Foo Inner {}
>>>>
>>>> interface IOuter { public interface IInner {}}
>>>> class Impl implements IOuter . @Foo IInner {}
>>>>
>>>> @Target(ElementType.TYPE_USE)
>>>> @Retention(RetentionPolicy.RUNTIME)
>>>> @interface Foo {}
>>>>
>>>
>


More information about the compiler-dev mailing list