As per the jvms-4.7.18 :
The i'th entry in the parameter_annotations table may, but is not required to, correspond to the i'th parameter descriptor in the method descriptor (§4.3.3).
For example, a compiler may choose to create entries in the table corresponding only to those parameter descriptors which represent explicitly declared parameters in source code. In the Java programming language, a constructor of an inner class is specified to have an implicitly declared parameter before its explicitly declared parameters (JLS §8.8.1), so the corresponding method in a class file has a parameter descriptor representing the implicitly declared parameter before any parameter descriptors representing explicitly declared parameters. If the first explicitly declared parameter is annotated in source code, then a compiler may create parameter_annotations[0] to store annotations corresponding to the second parameter descriptor.
And in asm MethodVisitor.visitParameterAnnotation
javadoc also states that:
parameter - the parameter index. This index must be strictly smaller than the number of parameters in the method descriptor, and strictly smaller than the parameter count specified in visitAnnotableParameterCount(int, boolean). Important note: a parameter index i is not required to correspond to the i'th parameter descriptor in the method descriptor, in particular in case of synthetic parameters
So the parameter index doesn't always match. Then how should I know which parameter annotation correspond to which parameter?
At first I thought I could use MethodParameters
attribute in jvms, which corresponds to MethodVisitor.visitParameter
in asm, which has parameter access_flags in it. I just need to filter out parameters which are ACC_SYNTHETIC
or ACC_MANDATED
, then the remaining parameters would just match the parameter annotations. But later I found out that MethodParameters
doesn't exist in classfile by default.(see my other question: how to show method parameter access_flags in java classfile) That means I can't get a parameter's access_flags in classfile, and the approach above doesn't work.
I also found related issues in asm's reposiroty:
- https://gitlab.ow2.org/asm/asm/-/merge_requests/44
- https://gitlab.ow2.org/asm/asm/-/issues/317814
- https://gitlab.ow2.org/asm/asm/-/issues/317788
In the discussions of above issues, it's decided that asm users should do the mapping between bytecode parameter indices and source code parameters if desired, but it doesn't mention how.
I'm also wondering how java reflection framework does the mapping, which may give me some inspiration, but I haven't checked that.
Back to the question, how should I map parameter annotations and parameters correctly?