3

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)

  • As far as I understand it, you cannot reflectively access local variables. – Slaw Oct 07 '19 at 18:18
  • Possible duplicate of [Java Reflection: How to get the name of a variable?](https://stackoverflow.com/questions/744226/java-reflection-how-to-get-the-name-of-a-variable) – Kaan Oct 07 '19 at 18:59
  • I am not necessarily interested in finding the name of the local variables or their values using reflection. I want to get the annotations on the local variables of a method. – Florin Blanaru Oct 07 '19 at 19:17
  • 2
    if you really need to get annotations like that, you could try to use some bytecode processing libraries, like Javassist or more low level ASM – GotoFinal Oct 10 '19 at 09:10

2 Answers2

2

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.

Kaan
  • 5,434
  • 3
  • 19
  • 41
  • However, from what I understand in the documentation: `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.` is that the annotations should be available. Please correct me if I am mistaken – Florin Blanaru Oct 07 '19 at 19:19
  • @FlorinBlanaru From [§9.6.4.2 of the JLS](https://docs.oracle.com/javase/specs/jls/se13/html/jls-9.html#jls-9.6.4.2): "_If `m` [the meta-annotation `Retention`] has an element whose value is `java.lang.annotation.RetentionPolicy.RUNTIME`, the reflection libraries of the Java SE Platform must make `a` [the annotation] available at run time_". All it says is that the **reflection libraries** must make the annotation available at run time; if one cannot access local variables via reflection then local variables are exempt from the requirement. – Slaw Oct 07 '19 at 20:48
2

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