如何在ASM中访问方法内的注释

huangapple go评论81阅读模式
英文:

How to visit annotation inside method in ASM

问题

抱歉,你的代码似乎有一些 HTML 转义字符,这些字符在翻译中可能会引起混淆。以下是没有 HTML 转义字符的内容的翻译:

各位,我无法访问使用 ASM MethodVisitor 注解的局部变量,我不知道该怎么办,请帮助我,我想获取值 "in method",但 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);
    }
}

希望这可以帮助你解决问题。如果你需要更多帮助,请随时提出。

英文:

guys, I can not visit local variable annotation use asm MethodVisitor, I do not know how to do, please help me, I want get the value "in method", but the MethodVisitor visitLocalVariableAnnotation() method does not called by the ASM logic, here is my code:

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

答案1

得分: 2

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

9.6.4.2. @Retention

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

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

  • 如果 m 有一个元素,其值为 java.lang.annotation.RetentionPolicy.SOURCE,那么 Java 编译器必须确保在出现 a 的类或接口的二进制表示中不包含 a。
  • 如果 m 有一个元素,其值为 java.lang.annotation.RetentionPolicy.CLASSjava.lang.annotation.RetentionPolicy.RUNTIME,那么 Java 编译器必须确保在出现 a 的类或接口的二进制表示中包含 a,除非 a 注解了局部变量声明,或者 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 平台的反射库必须在运行时使 a 可用。

如果 T 没有对应于 java.lang.annotation.Retention 的(元)注解 m,则 Java 编译器必须将 T 视为具有元注解 m,其元素值为 java.lang.annotation.RetentionPolicy.CLASS,就像实际存在这样的元注解一样。

(强调我的)

ASM 可以简单地不为不存在的信息生成事件。

英文:

This is expected, as per JLS 9.6.4.2 this information is simply not retained in the class file:

> ### 9.6.4.2. @Retention
>
> Annotations may be present only in source code, or they may be present in the binary form of a class or interface. An annotation that is present in the binary form may or may not be available at run time via the reflection libraries of the Java SE Platform. The annotation type java.lang.annotation.Retention is used to choose among these possibilities.
>
>If an annotation a corresponds to a type T, and T has a (meta-)annotation m that corresponds to java.lang.annotation.Retention, then:
>
> * If m has an element whose value is java.lang.annotation.RetentionPolicy.SOURCE, then a Java compiler must ensure that a is not present in the binary representation of the class or interface in which a appears.
>
> * If m has an element whose value is java.lang.annotation.RetentionPolicy.CLASS or java.lang.annotation.RetentionPolicy.RUNTIME, then a Java compiler must ensure that a is represented in the binary representation of the class or interface in which a appears, unless a annotates a local variable declaration or a annotates a formal parameter declaration of a lambda expression.
>
> An annotation on the declaration of a local variable, or on the declaration of a formal parameter of a lambda expression, is never retained in the binary representation. In contrast, an annotation on the type of a local variable, or on the type of a formal parameter of a lambda expression, is retained in the binary representation if the annotation type specifies a suitable retention policy.
>
> Note that it is not illegal for an annotation type to be meta-annotated with @Target(java.lang.annotation.ElementType.LOCAL_VARIABLE) and @Retention(java.lang.annotation.RetentionPolicy.CLASS) or @Retention(java.lang.annotation.RetentionPolicy.RUNTIME).
>
> If m has an element whose value is java.lang.annotation.RetentionPolicy.RUNTIME, the reflection libraries of the Java SE Platform must make a available at run time.
>
>If T does not have a (meta-)annotation m that corresponds to java.lang.annotation.Retention, then a Java compiler must treat T as if it does have such a meta-annotation m with an element whose value is java.lang.annotation.RetentionPolicy.CLASS.

(emphasis mine)

ASM can simply not emit events for information that is not present.

huangapple
  • 本文由 发表于 2020年8月18日 17:07:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/63465374.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定