JDK-8068891 : Type Annotations on Casts
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8u20,8u25
  • Priority: P4
  • Status: Resolved
  • Resolution: Won't Fix
  • OS: os_x
  • CPU: x86
  • Submitted: 2015-01-09
  • Updated: 2016-09-21
  • Resolved: 2016-09-21
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Darwin my.box 13.1.0 Darwin Kernel Version 13.1.0: Thu Jan 16 19:40:37 PST 2014; root:xnu-2422.90.20~2/RELEASE_X86_64 x86_64

A DESCRIPTION OF THE PROBLEM :
There are two problems with type annotations and casts:
1. The offset stored in the type annotation meta data in the class file is wrong. Respectively, the type annotation is associated with the wrong byte code instruction.
2. The compiler does not detect when a type annotation actually refines a type. It thinks it is a redundant cast and removes the according CHECKCAST instruction. As a result, the instruction list and the information stored in the type annotation are out of sync. Given issue 1 was fixed, the annotation would point to an instruction that was removed.

ADDITIONAL REGRESSION INFORMATION: 
Type annotations are only available in Java 1.8 so, to my knowledge, there is no prior regression.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Please use the test class that I attached to the issue. Compile it using 
javac -g TypeAnnotationProblems.java

The class incorporates the method "wrongIndex" to show case the first issue and the method "castElimination" to show case the second one.

Have a look at the produced byte code.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The offset in the type annotation stored with function "wrongOffset" should point to the CHECKCAST (index 12) instruction.

In the byte code of the "castElimination" function there should be a CHECKCAST instruction at the same position as in the function "wrongOffset" as they are almost identical.

As a reference, the Eclipse compiler has the right implementation: The type annotation meta data references the CHECKCAST instruction and the CHECKCAST instruction is not removed when it contains type annotations.
ACTUAL -
The offset of the type annotation at function "wrongOffset" is 11. It points to the ALOAD instruction for "this".
I added another function "wrongOffsetFunction" which shows that this is not a miscount by 1. There the offset in the type annotation meta data is 6 but should be 10.
It shows that the compiler or annotation support attaches the type information not to the cast but to the first instruction of the frame. This seems wrong.

In the "castElimination" function, the CHECKCAST instruction was removed from the byte code.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class TypeAnnotationProblems {
  
  @java.lang.annotation.Documented
  @java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
  @java.lang.annotation.Target(value = { java.lang.annotation.ElementType.TYPE_USE,
                                        java.lang.annotation.ElementType.TYPE_PARAMETER})
  public @interface Untainted {}

  protected static class MyState { public int _field = 1; }
  private MyState _state = null;

  public Object[] wrongOffset() {
    Object o = _state;
    return new Object[] { (@Untainted MyState) o };
  }

  public Object[] castElimination() {
    MyState o = _state;
    return new Object[] { (@Untainted MyState) o };
  }

  public Object[] wrongOffsetFunction() {
    return new Object[] { (@Untainted MyState) leaking() };
  }

  private Object leaking() {
    return _state;
  }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Since it seems that type annotations do not work on casts the work around is to always create a local variable and do the refinement on its type:

@Untainted MyState s = _state;

However, this requires to always create local variables.


Comments
Casts pointing to wrong instructions where the checkcast is present is addressed via https://bugs.openjdk.java.net/browse/JDK-8144168 There is no plan to address the casts being eliminated. See the thread of discussion at: http://mail.openjdk.java.net/pipermail/compiler-dev/2015-December/009883.html
21-09-2016

Casts pointing to wrong instructions is addressed via https://bugs.openjdk.java.net/browse/JDK-8144168
19-09-2016

Could reproduce the issue with JDK 8u20, 8u25 and 9 as described by the submitter. See attached bytecode file (test8u20.txt) for reference.
13-01-2015