I came across a strange effect in connection with annotations on method parameters in a nested class. Looks very much like a compiler issue to me. See below for details and steps to reproduce.
Compile the following class with javac (I used javac 1.7.0_51). Note the annotated parameter "boolean param3".
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class TestAnnotations {
public String a;
@Retention(RetentionPolicy.CLASS)
@interface MyAnnotation {}
protected class TestInner {
public TestInner(String param1, Object param2,
@MyAnnotation boolean param3) {}
public void accessField() {
System.out.println(TestAnnotations.this.a);
}
}
}
Then examine the nested class with javap (i.e. javap -p -v -c TestAnnotations$TestInner.class). Its constructor looks as follows.
public test.TestAnnotations$TestInner(test.TestAnnotations, java.lang.String,
java.lang.Object, boolean);
flags: ACC_PUBLIC
Code:
stack=2, locals=5, args_size=5
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:Ltest/TestAnnotations;
5: aload_0
6: invokespecial #2 // Method java/lang/Object."<init>":()V
9: return
LineNumberTable:
line 16: 0
RuntimeInvisibleParameterAnnotations:
0:
1:
2:
0: #18()
Note the number of annotations in the attribute RuntimeInvisibleParameterAnnotations - it's 3. At the same time we now observe 4 method parameters because of one additional test.TestAnnotations at the beginning (it is used to pass a reference to TestAnnotations.this into the inner class). This means, @MyAnnotation is now refering to Object param2, shifted by 1 to the left.
According to the Virtual Machine Specification the number of annotations should be the same as the number of method parameters:
num_parameters
The value of the num_parameters item gives the number of parameters of the method represented by the method_info structure on which the annotation occurs. (This duplicates information that could be extracted from the method descriptor (§4.3.3).)
Here we clearly see a violation. Does anyone know the reason? Is it really what it seems to be, just a compiler bug?