What is the use of RetentionPolicy.CLASS and RetentionPolicy.SOURCE? - java

What is the intended need for RetentionPolicy.CLASS and RetentionPolicy.SOURCE. In which annotation scenario, We can use these? I wanted some examples.
From the Java doc:
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 which scenario, We will go for this as developer?
SOURCE: Annotations are to be discarded by the compiler.
In which scenario, We will go for this as developer?

RetentionPolicy use to control the Lifetime and visibility of the annotations
RetentionPolicy.CLASS - The defined annotation will be stored in the .class file, but not available at runtime. This is the default retention policy if you do not specify any retention policy at all.
RetentionPolicy.SOURCE - The defined annotation will be ignored by the compiler when building the code. So the annotation is only available in the source code, and not in the .class files, and not at runtime too.
Use two annotations depending on the use case with that .class files are not polluted unnecessarily.
If the annotation is used by build tools that scan the code, you can use RetentionPolicy.SOURCE retention policy.

Related

#Retention of Java type checker annotations

The Java 8 type annotations (JSR 308) allow type checkers to perform static code analysis. For example, The Checker Framework can check for possible nullness via #NonNull annotations.
Various projects define their own NonNull annotations, for example:
org.checkerframework.checker.nullness.qual.NonNull
edu.umd.cs.findbugs.annotations.NonNull
javax.annotation.Nonnull
javax.validation.constraints.NotNull
lombok.NonNull
org.eclipse.jdt.annotation.NonNull
etc. (see The Checker Framework Manual, section 3.7)
For such annotations, I would expect the #interface to have #Retention(RetentionPolicy.CLASS), because they are usually not needed at runtime. Most importantly, the code does not have any runtime dependencies on the respective library.
While org.eclipse.jdt.annotation.NonNull follows this approach, most other NonNull annotations, like javax.annotation.Nonnull (JSR 305) and org.checkerframework.checker.nullness.qual.NonNull itself, have #Retention(RetentionPolicy.RUNTIME). Is there any particular reason for the RetentionPolicy.RUNTIME in these annotations?
Clarification: The Checker Framework supports annotations in comments for backward compatibility. However, using those in Java 8 just to avoid runtime dependencies seems like a dirty hack.
This is a good question.
For the purpose of static checking at compile time, CLASS retention would be sufficient. Note that SOURCE retention would not be sufficient, because of separate compilation: when type-checking a class, the compiler needs to read the annotations on libraries that it uses, and separately-compiled libraries are available to the compiler only as class files.
The annotation designers used RUNTIME retention to permit tools to perform run-time operations. This could include checking the annotations (like an assert statement), type-checking of dynamically-loaded code, checking of casts and instanceof operations, resolving reflection more precisely, and more. Not many such tools exist today, but the annotation designers wanted to accommodate them in the future.
You remarked that with #Retention(RetentionPolicy.CLASS), "the code does not have any runtime dependencies on the respective library." This is actually true with #Retention(RetentionPolicy.RUNTIME), too! See this Stack Overflow question:
Why doesn't a missing annotation cause a ClassNotFoundException at runtime? .
In summary, using CLASS retention costs a negligible amount of space at run time, enables more potential uses in the future, and does not introduce a run-time dependency.
In the case of the Checker Framework, it offers run-time tests such as isRegex(String). If your code uses such methods, your code will be dependent on the Checker Framework runtime library (which is smaller than the entire Checker Framework itself and has a more permissive license).
Each annotation has it's purpose!
javax.validation.constraints.NotNull
This ones is defined by the bean validation specification and is used to perform non-null check at runtime, so it needs to be retained at runtime to perform, for example, a form valdiation ...
#RetentionPolicy.SOURCE => usually used for documentation
#RetentionPocily.CLASS => allow to give some information to the compiler but not the JVM (for example, to perform code generation during compilation)
#RetentionPolicy.RUNTIME => allow to retrieve annotation information at the JVM level (so at runtime).
Regards,
Loïc

Annotation retention policy: what real benefit is there in declaring `SOURCE` or `CLASS`?

I know there are three retention policies for Java annotations:
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.
And although I understand their usage scenarios, I don't get why it is such an important thing to specify the retention policy that retention policies exist at all.
I mean, why aren't all the annotations just kept at runtime? Do they generate so much bytecode / occupy so much memory that stripping those not declared as RUNTIME does make that much difference?
To actually answer the question: to reduce dependencies. If there would be no distinction between e.g. SOURCE and RUNTIME, the "user" of the classes would have to provide all the dependencies the annotations come from. So only because that annotation is used by the IDE (SOURCE), the jar would have to be provided during runtime - which is unnecessary. If you try to get annotations from a class, where no jar is provided that actually provides the annotation, you will get a class not found exception.
Retention policy SOURCE is to aid IDEs, compilers and possibly code/doc generators to take advantage of annotations. These annotation do not make up part of compiled class and are discarded by compiler so not available during runtime.
For example, annotation java.lang.SuppressWarnings tells compiler not to report certain warnings.
Annotations to generate documentation can be of retention policy SOURCE.
Take a look at this post/answer Annotation SOURCE Retention Policy

Annotation SOURCE Retention Policy

From the Java doc:
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.
I understand the usages of RUNTIME (in order to use annotation with reflection) and CLASS (for the compiler) but I don't understand when it can be usefull to use
#Retention(RetentionPolicy.SOURCE)
Can you explain?
Things like #SuppressWarnings, #Override are annotations used by the compiler - not needed at runtime. For those RetentionPolicy.SOURCE would make sense. Also annotations can be used to generate code (look at Spring ROO) - such annotation are also not required at run time.
This answer makes perfect sense - https://stackoverflow.com/a/43910948/3009968.
You would not like to include a dependency, the desired effects of which are realized even before the code is compiled. E.g. #SuppressWarnings
You would not like to include a dependency which is used by compiler to let's say generate code but not at all required during runtime. E.g. as mentioned already in previous answer -spring roo.
RetentionPolicy.CLASS - The defined annotation will be stored in the .class file, but not available at runtime. This is the default retention policy if you do not specify any retention policy at all.
RetentionPolicy.SOURCE - The defined annotation will be ignored by the compiler when building the code. So the annotation is only available in the source code, and not in the .class files, and not at runtime too.

Tool to identify Java annotations in various Java APIs

I'm trying to identify places where annotation names are the same or similar to compile a list of these things to make sure our team knows where possible points of confusion can be found. For example, Guice #provides and RESTeasy #provider are similar enough in spelling but different enough in semantics as to confuse people so I'd like to call that out explicitly and explain the differences.
What I'm looking for is a tool or even a website that enumerates the annotations associated with packages. This might be a pipe dream, but before I manually start going through and collecting these things I thought I'd check.
I was considering writing one based on Javadoc that simply only pulled in the annotations but I don't have access to Java source files in many cases.
Any thoughts or suggestions?
In Eclipse you can use the standard method "Search for references" (context menu of a used annotation References -> Project) and you are getting a list where the annotations is used within your project.
I suggest to scan for annotations yourself and generate a list for that.
You can do that by writing your own implementation of an annotation processer, i.e. extend AbstractProcessor. Within this processor you can write a text file containing all Annotations. You can add this processor to your build procedure, then it will execute the processor when you build the project.
Another way to do this is using the Google Reflections library. This might be a bit more work since you would need to write a small programm to fetch the annotations and write the file.
I wrote such a tool: https://github.com/MoserMichael/ls-annotations
it decompiles the byte code and lists declarations (classes, functions, variables) with annotations only. You can also use it to find all classes/interfaces derived from a given class/inerface - and all the classes/interfaces derived from a given class/interface.
The tool uses the asm library to scan class files and to extract annotations. it can detect annotations with retention policy CLASS and RUNTIME. It can't detect annotations with retention policy SOURCE that are not put into bytecode, for example #Override is one of these.
Why not scanning your classpath and export all used annotations? Then just use some simple parsing / text compare to see the elements with almost the same name?

Is it possible to use Java annotations, to achieve a similar functionality as a preprocessor

Is it possible to create a preprocessor like functionality that is available in C and provided by Antenna. Can we use the APT tool to achieve this functionality? Are there any articles or links on similar topics?
Annotations are not meant as a tool to transform code; they just add metadata to code. You can't use annotations for conditional compilation, for example.
As Sun's tutorial on annotations says:
Annotations provide data about a program that is not part of the program itself. They have no direct effect on the operation of the code they annotate.
Wikipedia says:
When Java source code is compiled, annotations can be processed by compiler plug-ins called annotation processors. Processors can produce informational messages or create additional Java source files or resources, which in turn may be compiled and processed, but processors cannot modify the annotated code itself.
So an annotation processor plug-in is not going to be able to give you all of the functionality that the C preprocessor has.
You can perform compile-time tasks using the annotation processing framework. It's not as powerful as a preprocessor, since you can't do things like:
#RunOnlyOn(OS.Mac) public void someMethod() { ... }
Some good use cases for annotation processors are:
creating mapping files from annotated classes, e.g. create a hibernate mapping file;
creating indexes of classes which have certain annotation, e.g. create testng xml files from a source folder of test classes;
enforce compile-time constraints not usually available, e.g. having a no-arg constructor.
Please note that as of Java 6 APT is no longer needed, since all properly declared annotation processors take part in the compilation.

Categories