RFR: JDK-8267936: PreserveAllAnnotations option doesn't expose the annotation to Java code

Peter Levart plevart at openjdk.java.net
Mon May 31 23:55:20 UTC 2021


On Mon, 31 May 2021 22:36:52 GMT, David Holmes <david.holmes at oracle.com> wrote:

> > OTOH when CLASS retention is changing to RUNTIME, such as in this case, the ways of looking up are widening (there is some new desire to lookup the annotation at runtime via reflection). To facilitate that, the annotation maintainer changes the retention to RUNTIME. But unfortunately, old uses of the annotation are baked in the ` RuntimeInvisibleAnnotations` attributes of the classes that were compiled with the old version of the annotation when the retention was still CLASS. Until all such classes are recompiled, the JVM option can be used to make such annotation usages visible at runtime. That makes more sense to me.
> 
> That sounds like the code that wants to inspect the annotations is using
> knowledge that the target classes have been updated (in terms of the
> source change from CLASS to RUNTIME) but it only has access to old
> binaries. That scenario doesn't really make sense to me.

The code that wants to inspect the annotation knows that the annotation itself has been updated from CLASS to RUNTIME retention and is running with the new version of annotation on classpath. But the uses of that annotation are in other code - neither in the code that wants to inspect the annotation nor in the code that represents the annotation declaration and holds the @Retention meta-annotation use. The code that uses the annotation is the code that has been compiled before the annotation has been updated and therefore keeps annotation uses in the `RuntimeInvisibleAnnotations` attributes of class files representing that code. To be more concrete, let's illustrate with the example:


// annotation_v1.jar
@Retention(CLASS)
public @interface Ann {}

// use.jar (compiled with annotation_v1.jar on classpath, 
// so Use.class encodes the @Ann use in the `RuntimeInvisibleAnnotations` attribute)
@Ann
public class Use {}

// annotation_v2.jar (the new version of annotation that migrated to RUNTIME retention)
@Retention(RUNTIME)
public @interface Ann {}

// main.jar (running with: -cp use.jar:annotation_v2.jar:main.jar -XX:+PreserveAllAnnotations)
public class Main {
  public static void main(String[] a) {
    Ann ann = Use.class.getAnnotation(Ann.class);
    ...
  }
}



> 
> In any case the operation of the flag is very simple and has no bearing
> on how AnnotationParser works.

Exactly. It does affect which encoded annotation data is passed to AnnotationParser though. Either just `RuntimeVisibleAnnotations` or both `RuntimeVisibleAnnotations` and `RuntimeInvisibleAnnotations`. In any case the parser filters out annotations that don't have the RUNTIME retention in their declaration.

> 
> Cheers,
> David

Regards, Peter

-------------

PR: https://git.openjdk.java.net/jdk/pull/4245


More information about the core-libs-dev mailing list