首页 > 解决方案 > 如何在 ASM 中访问方法内部的注解

问题描述

伙计们,我无法使用asm MethodVisitor访问局部变量注释,我不知道该怎么做,请帮助我,我想获取“方法中”的值,但是ASM逻辑没有调用MethodVisitor visitLocalVariableAnnotation() 方法,这是我的代码:

@Retention(RetentionPolicy.CLASS)
@Target({ElementType.LOCAL_VARIABLE})
public @interface SendEvent {
    String value() default "hello every";
}


public class AnnotationTest {
    public void test() {
        @SendEvent(value = "in method")
        EventBase base =  new EventBase();
    }
}

public class AsmMethodVisitor extends MethodVisitor implements Opcodes {

    public AsmMethodVisitor(MethodVisitor methodVisitor) {
        super(ASM7, methodVisitor);
        System.out.println("== AsmMethodVisitor");
    }

    @Override
    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String descriptor, boolean visible) {
        System.out.println("== visitLocalVariableAnnotation");
        return super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible);
    }
}

标签: javajava-bytecode-asm

解决方案


这是预期的,根据JLS 9.6.4.2 ,此信息根本不会保留在类文件中:

9.6.4.2。@保留

注释可能只存在于源代码中,或者它们可能以类或接口的二进制形式存在。以二进制形式存在的注解在运行时可能通过 Java SE 平台的反射库可用,也可能不可用。注释类型java.lang.annotation.Retention用于在这些可能性中进行选择。

如果一个注解a对应一个类型 T,并且 T 有一个m对应于的(元)注解java.lang.annotation.Retention,那么:

  • 如果m有一个值为 的元素java.lang.annotation.RetentionPolicy.SOURCE,则 Java 编译器必须确保 a 不存在于出现 a 的类或接口的二进制表示中。

  • 如果m有一个值为java.lang.annotation.RetentionPolicy.CLASSor 的元素java.lang.annotation.RetentionPolicy.RUNTIME,则 Java 编译器必须确保 a 以出现 a 的类或接口的二进制表示形式表示,除非 a 注释局部变量声明或 a 注释 lambda 的形式参数声明表达。

    声明局部变量或声明 lambda 表达式的形式参数的注释永远不会保留在二进制表示中。相反,如果注释类型指定了合适的保留策略,则有关局部变量类型或 lambda 表达式的形式参数类型的注释将保留在二进制表示中。

    @Target(java.lang.annotation.ElementType.LOCAL_VARIABLE)请注意,使用and@Retention(java.lang.annotation.RetentionPolicy.CLASS)或对注释类型进行元注释并不违法@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)

    如果m有一个值为 的元素,java.lang.annotation.RetentionPolicy.RUNTIMEJava SE 平台的反射库必须a在运行时可用。

如果 T 没有对应于 的(元)注释 m java.lang.annotation.Retention,则 Java 编译器必须将 T 视为它确实具有这样的元注释 m,其中元素的值为java.lang.annotation.RetentionPolicy.CLASS

(强调我的)

ASM 不能简单地为不存在的信息发出事件。


推荐阅读