java - How do different retention policies affect my annotations?

ID : 20156

viewed : 23

Tags : javaannotationsjava

Top 5 Answer for java - How do different retention policies affect my annotations?

vote vote

94

  • RetentionPolicy.SOURCE: Discard during the compile. These annotations don't make any sense after the compile has completed, so they aren't written to the bytecode.
    Example: @Override, @SuppressWarnings

  • RetentionPolicy.CLASS: Discard during class load. Useful when doing bytecode-level post-processing. Somewhat surprisingly, this is the default.

  • RetentionPolicy.RUNTIME: Do not discard. The annotation should be available for reflection at runtime. Example: @Deprecated

Source: The old URL is dead now hunter_meta and replaced with hunter-meta-2-098036. In case even this goes down, I am uploading the image of the page.

Image (Right Click and Select 'Open Image in New Tab/Window') Screenshot of Oracle website

vote vote

88

According to your comments about class decompilation, here is how I think it should work:

  • RetentionPolicy.SOURCE: Won't appear in the decompiled class

  • RetentionPolicy.CLASS: Appear in the decompiled class, but can't be inspected at run-time with reflection with getAnnotations()

  • RetentionPolicy.RUNTIME: Appear in the decompiled class, and can be inspected at run-time with reflection with getAnnotations()

vote vote

72

Minimal runnable example

Language level:

import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy;  @Retention(RetentionPolicy.SOURCE) @interface RetentionSource {}  @Retention(RetentionPolicy.CLASS) @interface RetentionClass {}  @Retention(RetentionPolicy.RUNTIME) @interface RetentionRuntime {}  public static void main(String[] args) {     @RetentionSource     class B {}     assert B.class.getAnnotations().length == 0;      @RetentionClass     class C {}     assert C.class.getAnnotations().length == 0;      @RetentionRuntime     class D {}     assert D.class.getAnnotations().length == 1; } 

Bytecode level: using javap we observe that the Retention.CLASS annotated class gets a RuntimeInvisible class attribute:

#14 = Utf8               LRetentionClass; [...] RuntimeInvisibleAnnotations:   0: #14() 

while Retention.RUNTIME annotation gets a RuntimeVisible class attribute:

#14 = Utf8               LRetentionRuntime; [...] RuntimeVisibleAnnotations:   0: #14() 

and the Runtime.SOURCE annotated .class does not get any annotation.

Examples on GitHub for you to play with.

vote vote

64

Retention Policy: A retention policy determines at what point an annotation is discarded. It is s specified using Java's built-in annotations: @Retention[About]

1.SOURCE: annotation retained only in the source file and is discarded           during compilation. 2.CLASS: annotation stored in the .class file during compilation,          not available in the run time. 3.RUNTIME: annotation stored in the .class file and available in the run time. 
vote vote

53

  • CLASS :Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time.
  • RUNTIME :Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.
  • SOURCE :Annotations are to be discarded by the compiler.

Oracle Doc

Top 3 video Explaining java - How do different retention policies affect my annotations?

Related QUESTION?