RFR: JDK-8267936: PreserveAllAnnotations option isn't tested
David Holmes
david.holmes at oracle.com
Wed Jun 2 13:22:41 UTC 2021
Never mind ...
On 2/06/2021 10:47 pm, David Holmes wrote:
> On 2/06/2021 10:17 pm, Peter Levart wrote:
>> On Wed, 2 Jun 2021 11:40:13 GMT, Peter Levart <plevart at openjdk.org>
>> wrote:
>>
>>>> ...hm, it seems that mere presence of any RUNTIME annotation that
>>>> was RUNTIME already at the use compile time somehow affects
>>>> -XX:+PreserveAllAnnotations option so that now RUNTIME annotations
>>>> that were CLASS annotations at use compile time are not returned.
>>>> Checking VM logic...
>>>
>>> For example, if I try this:
>>>
>>> @Retention(CLASS)
>>> public @interface AnnA_v1 {}
>>>
>>> // An alternative version of AnnA_v1 with RUNTIME retention
>>> instead.
>>> // Used to simulate separate compilation (see AltClassLoader
>>> below).
>>> @Retention(RUNTIME)
>>> public @interface AnnA_v2 {}
>>>
>>> @Retention(RUNTIME)
>>> public @interface AnnB {}
>>>
>>> @AnnA_v1
>>> @AnnB
>>> public static class TestTask implements Runnable {
>>> @Override
>>> public void run() {
>>> AnnA_v1 ann1 =
>>> TestTask.class.getDeclaredAnnotation(AnnA_v1.class);
>>>
>>> ... then `ann1` is not returned, but if I comment out the `@AnnB`
>>> annotation use on TestTask, `ann1` is returned.
>>
>> I think we found a bug here. After all, this endeavor was not in vain.
>> The bug is in AnnotationParser:
>> https://github.com/openjdk/jdk/blob/6765f902505fbdd02f25b599f942437cd805cad1/src/java.base/share/classes/sun/reflect/annotation/AnnotationParser.java#L111
>>
>>
>> You see, the parser reads a 16bit integer from the start of
>> `rawAnnotations` and interprets it as the number of annotations to
>> parse. But OTOH, `rawAnnotations` may in case when
>> `-XX:+PreserveAllAnnotations` was used, contain two concatenated sets
>> of encoded annotations, each starting with its own count of
>> annotations. See how this concatenation is performed here:
>> https://github.com/openjdk/jdk/blob/6765f902505fbdd02f25b599f942437cd805cad1/src/hotspot/share/classfile/classFileParser.cpp#L3965
>>
>
> Two arrays are combined into one array and that is returned. What do you
> mean by "each starting with its own count" ?? Where is the code that
> shoves the apparent length into the start of the rawAnnotations byte[] ?
Sorry now I see what happens. We aren't combining two arrays of
annotations we're concatenating two streams of byes, each of which
represents a set of annotations, starting with the length.
The code that receives this on the JDK side doesn't seem to understand
that this is a possibility.
Though maybe this isn't a bug, maybe the AnnotationParser is
deliberately ignoring the second byte stream. (Though if it were
deliberate there should be some commentary to that affect!)
David
> Thanks,
> David
> -----
>
>> The concatenation is simply joining the arrays of u1 elements into a
>> concatenated array. So when both RuntimeVisibleAnnotations and
>> RuntimeInvisibleAnnotations are present (in case
>> -XX:+PreserveAllAnnotations was used), the concatenated array starts
>> with RuntimeVisibleAnnotations followed by RuntimeInvisibleAnnotations.
>>
>> AnnotationParser should not stop parsing when the 1st loop is finished
>> and the rawAnnotations is not exhausted yet. It should continue with
>> the 2nd round of parsing.
>>
>> -------------
>>
>> PR: https://git.openjdk.java.net/jdk/pull/4280
>>
More information about the core-libs-dev
mailing list