Operation offset for type annotations for NEW / CHECKCAST etc.
Michael Ernst
mernst at cs.washington.edu
Thu Feb 6 12:21:45 PST 2014
Thanks to quick work by Werner Dietl, the discussion at
https://bugs.openjdk.java.net/browse/JDK-8033803
already includes a fix.
(Also thanks to Alex for creating the bug report and to Eric for
integrating the fix into the version-9 repository.)
Thanks again, André, for the bug report. Please send us your other
remarks, too.
-Mike
> Subject: Re: Operation offset for type annotations for NEW / CHECKCAST
> etc.
> From: Alex Buckley <alex.buckley at oracle.com>
> To: type-annotations-dev at openjdk.java.net
> Date: Thu, 06 Feb 2014 11:27:12 -0800
>
> André,
>
> Thanks for reporting this.
>
> Note that a cast expression is represented in the
> RuntimeVisibleTypeAnnotations attribute differently than an instanceof
> or new expression. See Table 4.7.20-B. Still, the offset is specified as
> you would expect: "The value of the offset item specifies the code array
> offset of either the bytecode instruction corresponding to the cast
> expression, ...". (I recall we didn't want to mention 'checkcast'
> explicitly since it wasn't clear that all compilers would emit it all
> the time - but that's a sideshow.)
>
> Since there is clearly a bug here, I have filed:
>
> https://bugs.openjdk.java.net/browse/JDK-8033803
>
> Alex
>
> On 2/6/2014 8:31 AM, André Pankraz wrote:
>> Hi,
>>
>> because http://bugs.java.com/ didn't work for me, I would like to
>> describe some of my findings with type annotations here.
>> I used jdk-8-fcs-bin-b128-windows-x64-01_feb_2014 for this.
>>
>>
>> Type annotations for operations like instanceof / new are compiled
>> differently for Oracle JDK and Eclipse.
>> The type structure contains an offset in this case, which points to the
>> _previous_ operation for Oracle JDK and not to the relevant operation.
>>
>> Example:
>>
>> public static String testTypeParam() {
>> CharSequence str = "test";
>> return (@Nonnull String) str;
>> }
>>
>> Javac:
>> public static java.lang.String testTypeParam();
>> 0 ldc <String "test"> [5]
>> 2 astore_0 [str]
>> 3 aload_0 [str]
>> 4 checkcast java.lang.String [4]
>> 7 areturn
>> Line numbers:
>> [pc: 0, line: 61]
>> [pc: 3, line: 62]
>> Local variable table:
>> [pc: 3, pc: 8] local: str index: 0 type: java.lang.CharSequence
>> RuntimeVisibleTypeAnnotations:
>> #31 @org.decojer.cavaj.test.jdk8.
>> Nonnull(
>> target type = 0x47 CAST
>> offset = 3
>> type argument index = 0
>> )
>>
>> Offset 3 should be offset 4 for the checkcast operation (like Eclipse
>> compiler does).
>>
>>
>> The current specification for such type annotations says:
>>
>> "The value of the offset item specifies the code array offset of either
>> the
>> instanceof bytecode instruction corresponding to the instanceof
>> expression, the
>> new bytecode instruction corresponding to the new expression, or the
>> bytecode
>> instruction corresponding to the method or constructor reference
>> expression."
>>
>> I would guess the javac does it wrong / not spec conform and the offset
>> is to small?
>>
>> One serious consequence here is, that the ASM 5 visits the operations
>> and type annotations in different orders for Eclipse and JDK. The type
>> annotation visitor method is triggered before the operation visitor,
>> which is very bad to handle from the customizing view point.
>>
>>
>> Another recently found consequence is, that I think that this offset
>> calculation is totally wrong. ;)
>> Take this artificial method as example:
>>
>> public static String testArrays() {
>> @Size(max = 41)
>> @Nonnull
>> List<@Size(max = 42) CharSequence>[] @Size(max = 43) []
>> @Nonnull @Size(max = 44) [][] test = new @Size(max = 45) ArrayList
>> @Size(max = 46) [10][][] @Size(max = 47) @Size(max = 48) [];
>> return (@Size(max = 49) String) test[0][1][2][3].get(0);
>> }
>>
>> The offset for Size(49) is 6 and should be 21!
>>
>> If you look into the bytecode you can guess what happens. javac points
>> to the previous atomar stack expression, which is the new
>> ArrayList[][][][]. This results into multiple operations in bytecode
>> (many constants are needed for anewarray). So offset 6 points to
>> iconst_0, which is the first dimension stack value for the anewarray.
>>
>> Sry for long mail...also have other stuff / remarks, but this is the
>> most important one and the spec cannot be changed anymore anyway...
>>
>>
>> Cheers,
>> André
More information about the type-annotations-dev
mailing list