I need to know the annotations of a Java class. I am using Lombok.
Sample is:
#Data
#Builder
public class JavaBean {}
I tried java.lang.annotation.Annotation[] annotation = JavaBean.class.getAnnotations but it doesn't show Data and Builder.
I think you cannot see the annotations in JavaBean.class.getAnnotations because the #Retention is equals to SOURCE.
This kind of annotation is not needed at runtime.
For more details : Annotation SOURCE Retention Policy
Have a good day.
The answer is in source of these annotations:
#Target({TYPE, METHOD, CONSTRUCTOR})
#Retention(SOURCE)
public #interface Builder {
.....
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.SOURCE)
public #interface Data {
.....
Your code to get annotation is correct but it's #Retention(RetentionPolicy.SOURCE) which is playing role here.
Java defined 3 types of retention policies through java.lang.annotation.RetentionPolicy enumeration. It has SOURCE, CLASS and RUNTIME.
1) Annotation with retention policy SOURCE will be retained only with source code, and discarded during compile time.
2) Annotation with retention policy CLASS will be retained till compiling the code, and discarded during runtime.
3) Annotation with retention policy RUNTIME will be available to the JVM through runtime.
#Data and #Builder are marked with #Retention(SOURCE) which means these annotations are not present at runtime with your class hence you are not able to get these annotations..
Lombok annotations are pre-processed before the actual compilation, thus the compiled classes do not contain them as annotation, but rather as the already generated code.
Related
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.
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')
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()
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.
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.
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
What will happen when a Class or Interface who is annotated with an annotation of RetentionPolicy#RUNTIME is loaded in old JREs?
#FunctionalInterface // Java8 #Retention(RetentionPolicy.RUNTIME)
public interface MyFunctional {
}
Is above interface or any class implement that interface can run in JRE 7 or older?
Annotations are handled slightly different than other normal classes. If the JVM cannot load the annotation class for a runtime annotation, this annotation will be dropped and you cannot find hints anymore that there was an annotation.
As I know, #Documented annotation is used only by javadoc generator to generate javadocs from sources. So retention type should be SOURCE, but it's RUNTIME. Why?
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.ANNOTATION_TYPE)
public #interface Documented {
}
IMO that does not explain why #Documented needs runtime retention
Yes, it does. Lets say I ship a jar file without the sources. A user can build a proper javadoc using only information from classfiles the the reason that classfile have proper annotations is becase they are RetentionPolicy.RUNTIME.
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.
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().
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.
RetentionPolicy.CLASS are Useful when doing byte code-level post-processing.
Example :
https://github.com/thesmythgroup/DroidCook/blob/master/src/org/tsg/android/api/Annotations.java
http://retroweaver.sourceforge.net/
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.
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.
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')
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()
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.
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.
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