【问题标题】:Java 9+ unable to get annotations of local variables of methodJava 9+ 无法获取方法局部变量的注释
【发布时间】:2019-10-07 18:03:58
【问题描述】:

自 Java 9 起,以 LOCAL_VARIABLE 为目标的注解的保留方式发生了变化。 Now the bytecode representation will hold information about annotated local variables in each method. 另外,规范声明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.,如果我理解正确的话,它确认至少方法的局部变量上的注释应该可以通过反射获得。

但是,我一直在尝试使用反射来查找注释(或带注释的局部变量,或其值),但没有成功。

因此,是否有人知道如何执行此操作或是否可能?我正在使用 java 11。

例如,这是我的 Main 类,我尝试从测试方法中获取 @Parallel 注释。

public class Main {

public static void main(String[] args) {

    try {
        System.out.println("Main.class.getDeclaredMethod(\"test\").getAnnotations().length = " +
                Main.class.getDeclaredMethod("test").getAnnotations().length);

        System.out.println("Main.class.getDeclaredMethod(\"test\").getDeclaredAnnotations().length = " +
                Main.class.getDeclaredMethod("test").getDeclaredAnnotations().length);

        Annotation annotation = Main.class.getDeclaredMethod("test").getAnnotation(Parallel.class);
        System.out.println("annotation = " + annotation);

    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
}

void test() {
    @Parallel int a = 2;

    @Parallel int b = 4;
}
}

这是我的注释实现。我只是将所有内容添加为目标,因为我只是在测试它:

@Target({ ElementType.LOCAL_VARIABLE, ElementType.TYPE, ElementType.TYPE_USE, ElementType.TYPE_PARAMETER,
    ElementType.FIELD, ElementType.PARAMETER, ElementType.PACKAGE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Parallel {
}

运行javap -l -v -c -s Main.class 将显示:

void test();
descriptor: ()V
flags: (0x0000)
Code:
  stack=1, locals=3, args_size=1
     0: iconst_2
     1: istore_1
     2: iconst_4
     3: istore_2
     4: return
  LineNumberTable:
    line 22: 0
    line 24: 2
    line 25: 4
  RuntimeVisibleTypeAnnotations:
    0: #27(): LOCAL_VARIABLE, {start_pc=2, length=3, index=1}
      Parallel
    1: #27(): LOCAL_VARIABLE, {start_pc=4, length=1, index=2}
      Parallel

很明显,关于局部变量的注释信息在那里,我只是不知道反射是否能够检索它(或者是否有任何其他方法可以在运行时获取它)

【问题讨论】:

  • 据我了解,您不能反射性地访问局部变量。
  • 我不一定对使用反射查找局部变量的名称或其值感兴趣。我想获取方法局部变量的注释。
  • 如果你真的需要这样的注解,你可以尝试使用一些字节码处理库,比如Javassist或者更底层的ASM

标签: java reflection annotations


【解决方案1】:

.class 文件包含的信息多于通过反射公开的信息,但反射不会公开有关方法内的局部变量的信息。

我还没有找到正式声明的地方,但可以指向java.lang.reflect.Method 的Javadoc,它没有公开任何关于局部变量的方法。看看the reflection package 的其余部分,没有什么比Method 更合适的了。

【讨论】:

  • 但是,根据我在文档中的理解: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. 是注释应该可用。如果我错了,请纠正我
  • @FlorinBlanaru From §9.6.4.2 of the JLS: "如果m [元注释Retention] 有一个值为java.lang.annotation.RetentionPolicy.RUNTIME 的元素,Java SE 平台的反射库必须使a [注释] 在运行时可用”。它只是说 反射库 必须使注释在运行时可用;如果不能通过反射访问局部变量,则局部变量不受要求。
【解决方案2】:

最后,我设法使用低级字节码处理库 ASM 获取了有关它们的注释和字节码信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-18
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    • 2016-10-12
    相关资源
    最近更新 更多