Java 9+ unable to get annotations of local variables of method

Viewed 708

Since Java 9, the way retention works for annotations which have as a target LOCAL_VARIABLE has changed. Now the bytecode representation will hold information about annotated local variables in each method. Also, the specification states that 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., which, if I understand correctly, confirms that at least the annotations on the local variables of the method should be available through reflection.

However, I have been trying to use reflection to find the annotations (or local variables annotated, or their values) with no luck.

Therefore, does anyone have a clue on how to do this or if it is possible? I am using java 11.

As an example, this is my Main class where I try to get the @Parallel annotations from the test method.

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

And this is my annotation implementation. I've just added everything as a target since I am only testing it:

@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 {
}

Running javap -l -v -c -s Main.class will show this:

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

It's clear that information about the annotations on the local variables is there, I just don't know if reflection is able retrieve it (or if there's any other way to get it at runtime)

2 Answers

A .class file contains more information than is exposed via reflection, but reflection does not expose information about local variables within a method.

I haven't found where this is formally stated, but can point to the Javadoc for java.lang.reflect.Method which has no methods exposing anything about local variables. Looking at the rest of the the reflection package, there's nothing else would that would be a better fit than Method.

In the end I have managed to get the annotations and bytecode information about them using the low level bytecode processing library ASM.

Related