references to non-static types from annotations

Liam Miller-Cushon cushon at
Fri Apr 8 17:35:49 UTC 2016

javac fails to reject references to non-static classes inside annotations,
and instead produces invalid output.


class Test<T> {
  @Retention(RetentionPolicy.RUNTIME) @interface A { Class<?> value(); }
  @A(I.class) interface C {}
  class I {}
  public static void main(String[] args) {

The reference to I.class in `@A(I.class) interface C {}` refers to the
non-static type Test<T>.I, but the annotation is a static context. The
compiler produces this attribute for the annotation:

$ javap -v -private 'Test$C'
   #9 = Utf8               LTest$A;
  #10 = Utf8               value
  #13 = Utf8               LTest<TT;>.I;
  0: #9(#10=c#13)

JVMS requires a class_info_index to be the index of a Utf8_info
representing a return descriptor, and `LTest<TT;>.I;` is not a legal return

The bytecode is rejected when read during reflection, and during subsequent

$ javac && java Test
Exception in thread "main" java.lang.ClassCastException:
sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast
to java.lang.Class

$ javac -implicit:none error: cannot access C
class Other { Class<?> clazz = Test.C.class; }
  bad class file: ./Test$C.class
    undeclared type variable: T
    Please remove or make sure it appears in the correct subdirectory of
the classpath.

Recording that a static context is being entered in HeaderPhase before
calling annotateLater fixes the bug, and doesn't break any existing tests.
The compatibility impact of the fix is minimal: I tried patching javac and
building a large code base, and only found a single instance of the problem.

If the proposed fix sounds reasonable, I'd be happy to clean up the patch
for review.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the compiler-dev mailing list