Operation offset for type annotations for NEW / CHECKCAST etc.

André Pankraz andre at pankraz.de
Thu Feb 6 08:31:35 PST 2014


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.


    public static String testTypeParam() {
        CharSequence str = "test";
        return (@Nonnull String) str;

  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
      #31 @org.decojer.cavaj.test.jdk8.
        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,
new bytecode instruction corresponding to the new expression, or the
instruction corresponding to the method or constructor reference

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)
        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...

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/type-annotations-dev/attachments/20140206/30f19f47/attachment.html 

More information about the type-annotations-dev mailing list