187
votes

Can anyone explain in a clear way the practical differences between the java.lang.annotation.RetentionPolicy constants SOURCE, CLASS, and RUNTIME?

I'm also not exactly sure what the phrase "retaining annotation" means.

5
The documentation ( java.sun.com/j2se/1.5.0/docs/api/java/lang/annotation/… ) is very clear.True Soft
yes I already read but I don't understand in practice how it works. In fact if i try 'this phrase': """" Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time. """ and then open a decompiled class where I put an annotation with retention policy CLASS I don't find nothing...xdevel2000
Then your decompiler doesn't seem to support annotations. jd-gui works fine.musiKk
Thanks the problem was my decompiler dj and jad ... jd-gui show me!!xdevel2000

5 Answers

221
votes
  • 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

64
votes

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()

22
votes

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.

7
votes

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.
0
votes
  • 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