如何使用ASM将类文件中的参数注解映射到对应方法参数
根据JVMS-4.7.18规范:
parameter_annotations表中的第i项不一定必须与方法描述符中的第i个参数描述符对应。
例如,编译器可能仅为那些表示源代码中显式声明参数的参数描述符在表中创建条目。在Java编程语言中,内部类的构造函数被规定在其显式声明的参数之前有一个隐式声明的参数,因此类文件中对应的方法在任何表示显式声明参数的参数描述符之前,有一个表示隐式声明参数的参数描述符。如果源代码中第一个显式声明的参数带有注解,编译器可能会创建parameter_annotations[0]来存储对应第二个参数描述符的注解。
另外,ASM的MethodVisitor.visitParameterAnnotation文档也指出:
parameter - 参数索引。该索引必须严格小于方法描述符中的参数数量,且严格小于visitAnnotableParameterCount(int, boolean)中指定的参数数量。重要提示:参数索引i不一定必须与方法描述符中的第i个参数描述符对应,尤其是在存在合成参数的情况下。
由此可知,参数注解的索引和方法描述符里的参数索引并不总是匹配的,那该如何确定哪个参数注解对应哪个方法参数?
我最初的思路是利用JVMS中的MethodParameters属性(对应ASM的MethodVisitor.visitParameter),它包含参数的access_flags,只要过滤掉带有ACC_SYNTHETIC或ACC_MANDATED标记的参数,剩余参数就能和参数注解匹配。但后来发现MethodParameters并非默认存在于类文件中,这意味着无法从类文件中获取参数的access_flags,这个方法走不通。
我还在ASM仓库里找到几个相关问题:
- 合并请求#44
- 问题#317814
- 问题#317788
这些问题的讨论中明确,ASM用户需要自行实现字节码参数索引与源代码参数的映射,但并未说明具体实现方法。我也想过参考Java反射框架的实现逻辑,但还没开始研究。
现在回到核心问题:如何正确映射参数注解与方法参数?
内容的提问来源于stack exchange,提问作者sify

