206

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.

stkent
  • 19,772
  • 14
  • 85
  • 111
xdevel2000
  • 20,780
  • 41
  • 129
  • 196
  • 5
    The documentation ( http://java.sun.com/j2se/1.5.0/docs/api/java/lang/annotation/RetentionPolicy.html ) is very clear. – True Soft Jun 24 '10 at 07:35
  • 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 Jun 24 '10 at 07:48
  • 2
    Then your decompiler doesn't seem to support annotations. jd-gui works fine. – musiKk Jun 24 '10 at 07:59
  • Thanks the problem was my decompiler dj and jad ... jd-gui show me!! – xdevel2000 Jun 24 '10 at 08:18

5 Answers5

235
  • 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

Edric
  • 24,639
  • 13
  • 81
  • 91
Favonius
  • 13,959
  • 3
  • 55
  • 95
  • 2
    thanks for the quote, the most interesting here is the use case for `RetentionPolicy.CLASS` – Max Feb 12 '13 at 10:22
  • 2
    can you explain why RetentionPolicy.class is interesting / surprisingly the default? – sudocoder Jan 12 '15 at 21:33
  • 1
    @sudocoder - Refer to these links: http://stackoverflow.com/a/5971247/373861 and http://stackoverflow.com/a/3849602/373861. I beleive this particular policy is needed for bytecode instrumentation. Though I never used it myself. – Favonius Jan 15 '15 at 06:56
  • At the end it says *In the next article in this series, I'll show how Java's reflection capabilities have been enhanced to help you discover annotations at runtime and how the Annotation Processing Tool "apt" lets you use annotations at build-time.*, where is this article? – Sushant Jan 14 '16 at 09:01
  • @Sushant: Well I am not sure where is it :). Though `apt` is deprecated refer to this http://docs.oracle.com/javase/7/docs/technotes/guides/apt/GettingStarted.html. For discovering annotation using reflection there are multiple tutorials on internet. You can start by looking into `java.lang.Class::getAnno*` and similar methods in `java.lang.reflect.Method` and `java.lang.reflect.Field`. – Favonius Jan 14 '16 at 16:25
  • I could not find fourth [article](http://www.oracle.com/technetwork/articles/hunter-meta-3-092019.html) – overexchange Sep 17 '17 at 00:04
73

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

ewernli
  • 38,045
  • 5
  • 92
  • 123
22

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.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
10

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.
yoAlex5
  • 29,217
  • 8
  • 193
  • 205
Ferdous Wahid
  • 3,227
  • 5
  • 27
  • 28
0
  • 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

Michael Wong
  • 361
  • 4
  • 6