RetentionPolicy CLASS vs. RUNTIME

JavaAnnotations

Java Problem Overview


What is the practical difference between RetentionPolicy.CLASS and RetentionPolicy.RUNTIME?

It looks like both are recorded into the bytecode and both may be accessed at the run-time anyway.

Java Solutions


Solution 1 - Java

>both may be accessed at the run-time anyway.

That's not what the javadoc says:

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.

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

In practice, I'm not aware of any use-cases for CLASS. It would only be useful if you wanted to read the bytecode programmatically, as opposed to via the classloader API, but that's a very specialised case, and I don't know why you wouldn't just use RUNTIME.

Ironically, CLASS is the default behaviour.

Solution 2 - Java

> It looks like both are recorded into the bytecode and both may be accessed at the run-time anyway.

False for basic built-in annotation interfaces like getAnnotations. E.g.:

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;
}

so the only way to observe a RetentionPolicy.CLASS annotation is by using a bytecode parser.

Another difference is that the Retention.CLASS annotated class gets a RuntimeInvisible class attribute, while Retention.RUNTIME annotations get a RuntimeVisible class attribute. This can be observed with javap.

Examples on GitHub for you to play with.

Solution 3 - Java

By default, annotations are not accessible through Reflection APIs. (RetentionPolicy.CLASS is the default retention policy)

You can specify for your custom annotation if it should be available at runtime, for inspection via reflection. You do so by annotating your annotation definition with the @Retention annotation.

Try this simple example

@Retention(RetentionPolicy.RUNTIME)
public @interface Version {
    int test();
}

@Version(test= 1)
public class Engineer{
   //code
}

public class Main {
        
    public static void main(String[] args) {
        Engineer engineer = new Engineer();
    
        Annotation[] annotations = engineer.getClass().getAnnotations();
        System.out.printf("%d annotations found.", annotations.length);
    }
}

Try to run the code again by changing the RetentionPolicy of the Version annotation to RetentionPolicy.CLASS and check the difference.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDimaView Question on Stackoverflow
Solution 1 - JavaskaffmanView Answer on Stackoverflow
Solution 2 - JavaCiro Santilli Путлер Капут 六四事View Answer on Stackoverflow
Solution 3 - JavaYuresh KarunanayakeView Answer on Stackoverflow