On 09/08/2015 06:12 PM, Alex Buckley wrote:
Jeff,

I confirm (JDK 8u40) that in an instance/static initializer, where a local variable declaration includes an annotated type, there is no RuntimeVisibleTypeAnnotations attribute emitted for the type annotation! This is so even when the correct meta-annotations appear on the declaration of the annotation type:

  @Target(ElementType.TYPE_USE)
  @Retention(RetentionPolicy.RUNTIME)

In a ctor, the same local variable declaration does cause a RuntimeVisibleTypeAnnotations attribute to be emitted for the type annotation.

I assume the difference stems from the fact that an annotation on a local variable declaration (the declaration, not its type) was traditionally never emitted into the class file, regardless of @Target. In SE 8, an annotation on the type of a local variable declaration can be emitted into the class file, but presumably some old code in javac is special-casing initializers and wasn't updated to understand type annotations therein.

Jon,

Can you confirm my presumption?

I could believe there is a bug in this area, if that is what you are asking.

-- Jon


Alex

On 9/8/2015 3:28 PM, Jeff Hain wrote:

Hi Alex.



 >Either this is a huge bug in javac or you're not looking in the right
>place. The code in an instance initializer compiles into the same <init> >method as the code in a constructor, so I would expect the <init> method
 >to have a RuntimeVisibleTypeAnnotations attribute whether the local
 >variable (whose type is annotated) exists in {...} or a ctor.



Here are the classes I parsed to test that (using the same annotation as
I described),
and bellow their respective constant pool, which are quite different,
with the
non-constructor one NOT containing RuntimeVisibleTypeAnnotations
(compiled with JDK8_60, -source 1.8 -target 1.8 (I guess the defaults
anyway)):



/**
  * <init> method.
  */
public static class MyMethodCodeInitBlock {
     {
         // String will not make it into the class file.

@A_TYPE_USE_R_COMPLEX(nbrClsArr={Long.class},tooStrong="",rounding=RoundingMode.UNNECESSARY,doc=@Documented)
         Integer foo = 1;
         try {
             MyBlackHole.blackHole(foo);
         } catch (RuntimeException e) {
             throw e;
         }
     }
}

/**
  * <init> method.
  */
public static class MyMethodCodeConstructor {
     public MyMethodCodeConstructor() {
         // String will not make it into the class file.

@A_TYPE_USE_R_COMPLEX(nbrClsArr={Long.class},tooStrong="",rounding=RoundingMode.UNNECESSARY,doc=@Documented)
         Integer foo = 1;
         try {
             MyBlackHole.blackHole(foo);
         } catch (RuntimeException e) {
             throw e;
         }
     }
}



pool[4] : class name utf8 index = 22
pool[5] : class name utf8 index = 24
pool[6] : class name utf8 index = 27
pool[7] : utf8 = <init>
pool[8] : utf8 = ()V
pool[9] : utf8 = Code
pool[10] : utf8 = LineNumberTable
pool[11] : utf8 = StackMapTable
pool[12] : class name utf8 index = 24
pool[13] : class name utf8 index = 28
pool[14] : class name utf8 index = 22
pool[15] : utf8 = SourceFile
pool[16] : utf8 = ClassDepsParserTest.java
pool[17] : descriptor (TAN) utf8 index = 8 = ()V
pool[18] : class name utf8 index = 28
pool[19] : descriptor (TAN) utf8 index = 30 = null
pool[20] : class name utf8 index = 31
pool[21] : descriptor (TAN) utf8 index = 34 = null
pool[22] : utf8 = java/lang/RuntimeException
pool[23] : class name utf8 index = 35
pool[24] : utf8 = net/jadecy/code/ClassDepsParserTest$MyMethodCodeInitBlock
pool[25] : utf8 = MyMethodCodeInitBlock
pool[26] : utf8 = InnerClasses
pool[27] : utf8 = java/lang/Object
pool[28] : utf8 = java/lang/Integer
pool[29] : utf8 = valueOf
pool[30] : utf8 = (I)Ljava/lang/Integer;
pool[31] : utf8 = net/jadecy/code/ClassDepsParserTest$MyBlackHole
pool[32] : utf8 = MyBlackHole
pool[33] : utf8 = blackHole
pool[34] : utf8 = (Ljava/lang/Object;)Z
pool[35] : utf8 = net/jadecy/code/ClassDepsParserTest

pool[4] : class name utf8 index = 36
pool[5] : class name utf8 index = 38
pool[6] : class name utf8 index = 40
pool[7] : utf8 = <init>
pool[8] : utf8 = ()V
pool[9] : utf8 = Code
pool[10] : utf8 = LineNumberTable
pool[11] : utf8 = StackMapTable
pool[12] : class name utf8 index = 38
pool[13] : class name utf8 index = 41
pool[14] : class name utf8 index = 36
pool[15] : utf8 = RuntimeVisibleTypeAnnotations
pool[16] : class name utf8 index = 42
pool[17] : utf8 = A_TYPE_USE_R_COMPLEX
pool[18] : utf8 = InnerClasses
pool[19] : utf8 = Lnet/jadecy/code/ClassDepsParserTest$A_TYPE_USE_R_COMPLEX;
pool[20] : utf8 = nbrClsArr
pool[21] : utf8 = Ljava/lang/Long;
pool[22] : utf8 = tooStrong
pool[23] : utf8 =
pool[24] : utf8 = rounding
pool[25] : utf8 = Ljava/math/RoundingMode;
pool[26] : utf8 = UNNECESSARY
pool[27] : utf8 = doc
pool[28] : utf8 = Ljava/lang/annotation/Documented;
pool[29] : utf8 = SourceFile
pool[30] : utf8 = ClassDepsParserTest.java
pool[31] : descriptor (TAN) utf8 index = 8 = ()V
pool[32] : class name utf8 index = 41
pool[33] : descriptor (TAN) utf8 index = 44 = null
pool[34] : class name utf8 index = 45
pool[35] : descriptor (TAN) utf8 index = 48 = null
pool[36] : utf8 = java/lang/RuntimeException
pool[37] : class name utf8 index = 49
pool[38] : utf8 =
net/jadecy/code/ClassDepsParserTest$MyMethodCodeConstructor
pool[39] : utf8 = MyMethodCodeConstructor
pool[40] : utf8 = java/lang/Object
pool[41] : utf8 = java/lang/Integer
pool[42] : utf8 = net/jadecy/code/ClassDepsParserTest$A_TYPE_USE_R_COMPLEX
pool[43] : utf8 = valueOf
pool[44] : utf8 = (I)Ljava/lang/Integer;
pool[45] : utf8 = net/jadecy/code/ClassDepsParserTest$MyBlackHole
pool[46] : utf8 = MyBlackHole
pool[47] : utf8 = blackHole
pool[48] : utf8 = (Ljava/lang/Object;)Z
pool[49] : utf8 = net/jadecy/code/ClassDepsParserTest



-Jeff


Reply via email to