27
votes

according to Java Annotation API:

  • RetentionPolicy.CLASS Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time.

  • RetentionPolicy.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.

I am looking for a sample of "CLASS" retention policy. when we need to use this policy instead of RUNTIME policy.

4

4 Answers

20
votes

CLASS Annotations are used in obfuscator tools like http://proguard.sourceforge.net . For example annotation @KeepName disables name mangling when you need to have your class name unchanged to be able to call methods like Class.forName().

11
votes

Of all of the large number of libraries I have in my current project. the only examples I can find are in the Google Guava library, for example com.google.common.annotations.GwtCompatible.

I'm not really sure why they chose this retention policy, though - perhaps for tools support, where the tools read the class files themselves, rather than going through the reflection API. I'm not sure that I really see the point of this distinction, though.

4
votes

Minimal example

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.CLASS)
@interface RetentionClass {}

@Retention(RetentionPolicy.RUNTIME)
@interface RetentionRuntime {}

public static void main(String[] args) {
    @RetentionClass
    class C {}
    assert C.class.getAnnotations().length == 0;

    @RetentionRuntime
    class D {}
    assert D.class.getAnnotations().length == 1;
}

If we use javap on the annotated classes, we see 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()

So the information is present on both cases in the bytecode.

Therefore, Runtime.CLASS can be used to associate arbitrary metadata to a class which bytecode manipulation tools can use, without interfering with runtime-visible behavior.

Examples on GitHub for you to play with.