如何在ASM中的方法内部访问注释 9.6.4.2 @Retention

问题描述

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

@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);
    }
}

解决方法

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

9.6.4.2。 @Retention

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

如果注释a对应于类型T,并且T具有(元)注释m对应于java.lang.annotation.Retention,则:

  • 如果m的元素值为java.lang.annotation.RetentionPolicy.SOURCE,则Java编译器必须确保a出现在类或接口的二进制表示形式中。 / p>

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

    在声明局部变量或在lambda表达式的形式参数上的注释从未保留在二进制表示中。 ,如果注释类型指定了适当的保留策略,则在二进制表示形式中保留有关局部变量类型或lambda表达式的形式参数类型的注释。

    请注意,使用@Target(java.lang.annotation.ElementType.LOCAL_VARIABLE)@Retention(java.lang.annotation.RetentionPolicy.CLASS)@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)对注释类型进行元注释是非法的。

    如果m的元素值为java.lang.annotation.RetentionPolicy.RUNTIME,则Java SE Platform的反射库必须在运行时使a可用。

如果T没有对应于java.lang.annotation.Retention的(元注释)m,那么Java编译器必须将T视为确实具有这样的元注释m,其元素值为{{ 1}}。

(重点是我的)

ASM根本无法针对不存在的信息发出事件。