How does the javac tool process the annotations in the source code? Are they compiled and translated into bytecode or they will be treated in a way that resembles processing the comment lines?
Annotations are handled by the compiler in a special way. They get parsed, but most annotations do not mean anything to the compiler. Some do, for example, if you incorrectly use the #Override annotation, a compile-time error will occur. You can find a list of compiler-relevant annotations here.
After that, the behavior depends on the annotation type:
If an annotation has its rentention policy set to RUNTIME or CLASS, it will actually be included in the class file. If the retention policy is RUNTIME, the annotation can even be accessed at runtime via reflection. Many libraries use this to provide some additional comfort, e.g. JUnit uses #Test to mark methods which implement unit tests and looks for those at runtime.
In addition, the java compiler allows to implement so called 'annotation processors', which can access the AST of the compilation unit and process annotations. This is another proof that the compiler does indeed handle annotations.
Related
I may be just looking in the wrong direction but I find the JSE documentation on annotation processing very ... sparse. I want to write an annotation processor which processes annotated String fields and local variables to substitute them with a computed String expression. This should not be too complicated but I'm pretty lost in the Javadoc for javax.annotation.processing.
EDIT: I need to process annotations at compile time because I want to modify the generated code. It should replace annotated constant String expressions with a computed String expression.
This can not be done with a compile time annotation processor. Compile time time annotation processors can only generate new files (and classes) they can not modify existing classes. You can do reflection at runtime but strictly speaking you that is not called annotation processing. Also you won't have access to local variables.
If you're looking on how to write a compile time annotation processor check out https://github.com/pellaton/spring-configuration-validation-processor
Two tools that do this are Project Lombok and DuctileJ. Both of these tools existed at the time the question was originally asked; additional tools now surely exist.
The key idea is to write an annotation processor that traverses and modifies the program's AST (abstract syntax tree) during compilation, before code generation. The compiler won't change the source code on disk, but the generated .class file will reflect the changes that your annotation processor makes.
You may be able to adapt one of these tools to suit your needs, or you could implement your own tool inspired by their implementation techniques.
Compile-time processing has two advantages over class-file processing. One is that the compiler usually has more information than is available from compiled code. Another is that everything happens in one step, during compilation, rather than requiring the developer to run a separate tool to rewrite the .class files after compilation.
Check
Javassist http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
ASM http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
Byteman (for runtime) http://www.jboss.org/byteman/
Is annotation processing still an active part of Java 6+, or is it something that has been deprecated/discouraged/obsolesced. If obsolesced, why (why is it no longer needed/useful)? And if it's still extremely useful and "active" (a new Java project developing against the Java 6+ JDK would still benefit from it), please confirm/correct my understanding of how annotation processors are used:
You create your own annotation class, say #MyAnnotation
You mark certain classes, methods, fields, etc. with #MyAnnotation
During the build process, you invoke your custom MyAnnotationProcessor (how?)
The processor scans your classpath for instances of #MyAnnotation
Typically, an annotation processor does dynamic bytecode injection, modifying/enhancing your compiled classes on-the-fly
Correct.
Correct.
Correct. Typically you will extend AbstractProcessor. You specify your MyAnnotationProcessor class using the ServiceLoader pattern - this makes it discoverable to the compiler. The Processor Javadoc contains some information on creating this class.
Correct.
This part is not correct. The annotation processor framework does not give you the ability to modify classes. You will need to use some post-compile process to do this as part of your build. What it does allow you to do is create new files. These may be simple resources, new Java source files (that will subsequently be required and eligible to the annotation processor during the same compile), or Java class files. You may also perform custom checks on source code and write errors to the log (causing the compile to fail).
I hope that addresses your understanding questions.
I am trying to understand the retention policy from Java 1.5. But not getting a clear picture.
As per JavaDoc,
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
what does it mean by "discarded"?
Is it like the class file will not have the particular annotated element in it by marking it with SOURCE?
SOURCE annotations are only present in the source file.
When the compiler "discards" the annotation, it is essentially ignoring that the annotation even exists. Source annotations basically serve the same purpose as commenting code.
The annotated element is not affected.
#Retention is what you'd call a meta-annotation: it only applies to other annotation interfaces. As such it also only affects the annotation it is applied to.
For example if you had an annotation named #Foo that is itself annotated with #Retention(RetentionPolicy.SOURCE), then the #Foo annotation (on another element) would be parsed by the compiler, but not stored in the resulting .class file (so if you'd ask the runtime if the element had the #Foo annotation, you'd get a negative answer).
This can be useful if you use an annotation purely for documentation purposes or if you want to handle it with annotation processing (during the compile step).
In the Java programming language, annotations can be used as a special form of syntactic metadata in the source code.
Classes, methods, variables, parameters and packages may be annotated. The annotations can be embedded in class files generated by the compiler and may be RETAINED by the Java virtual machine and thus influence the run-time behaviour of an application.
A retention policy determines at what point annotation should be discarded.
Annotation with retention policy RUNTIME will be available to the JVM through runtime.
I may be just looking in the wrong direction but I find the JSE documentation on annotation processing very ... sparse. I want to write an annotation processor which processes annotated String fields and local variables to substitute them with a computed String expression. This should not be too complicated but I'm pretty lost in the Javadoc for javax.annotation.processing.
EDIT: I need to process annotations at compile time because I want to modify the generated code. It should replace annotated constant String expressions with a computed String expression.
This can not be done with a compile time annotation processor. Compile time time annotation processors can only generate new files (and classes) they can not modify existing classes. You can do reflection at runtime but strictly speaking you that is not called annotation processing. Also you won't have access to local variables.
If you're looking on how to write a compile time annotation processor check out https://github.com/pellaton/spring-configuration-validation-processor
Two tools that do this are Project Lombok and DuctileJ. Both of these tools existed at the time the question was originally asked; additional tools now surely exist.
The key idea is to write an annotation processor that traverses and modifies the program's AST (abstract syntax tree) during compilation, before code generation. The compiler won't change the source code on disk, but the generated .class file will reflect the changes that your annotation processor makes.
You may be able to adapt one of these tools to suit your needs, or you could implement your own tool inspired by their implementation techniques.
Compile-time processing has two advantages over class-file processing. One is that the compiler usually has more information than is available from compiled code. Another is that everything happens in one step, during compilation, rather than requiring the developer to run a separate tool to rewrite the .class files after compilation.
Check
Javassist http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
ASM http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
Byteman (for runtime) http://www.jboss.org/byteman/
I am just looking to write some annotation which can execute at runtime, before or immediately after a service method is invoked.
I don't know if they are executed at runtime or compile time.
Annotations don't execute; they're notes or markers that are read by various tools. Some are read by your compiler, like #Override; others are embedded in the class files and read by tools like Hibernate at runtime. But they don't do anything themselves.
You might be thinking of assertions instead, which can be used to validate pre and post conditions.
Annotations are just markers. They don't execute and do anything.
You can specify different retention policies:
SOURCE: annotation retained only in the source file and is discarded during compilation.
CLASS: annotation stored in the .class file during compilation, not available in the run time.
RUNTIME: annotation stored in the .class file and available in the run time.
More here: http://www.java2s.com/Tutorial/Java/0020__Language/SpecifyingaRetentionPolicy.htm
Actually, when you define an annotation, you must specify the parameter #Retention, which defines whether the annotation is available in the source code (SOURCE), in the class files (CLASS), or at run time (RUNTIME).
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnnotation {}
It depends on retention policy attached with that annotation.
A retention policy determines at what point annotation should be
discarded. Java defined 3 types of retention policies through
java.lang.annotation.RetentionPolicy enumeration. It has SOURCE, CLASS and RUNTIME.
Annotation with retention policy SOURCE will be retained only with
source code, and discarded during compile time.
Annotation with retention policy CLASS will be retained till
compiling the code, and discarded during runtime.
Annotation with retention policy RUNTIME will be available to the
JVM through runtime.
The retention policy will be specified by using java built-in
annotation #Retention, and we have to pass the retention policy
type. The default retention policy type is CLASS.
Annotations don't have effect on your code, they're here to provide information to be evaluated by the compiler or other tools.
Annotations have a number of uses, among them:
Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings.
Compiler-time and deployment-time processing — Software tools can process annotation
information to generate code, XML files, and so forth.
Runtime processing — Some annotations are available to be examined at runtime.
See this page.
Annotations are only markers at the source code. They will be used by tools like IDE, compiler or annotation processors.
You can define with #Retention if a annotation should be evaluated in the source, class or runtime.
If you would like define your owned annotations and only you has the knowledge what the annotation should be do, so you should write an annotation processor too.
(but this is not simple - maybe)
They actually can be read in both environments, depending on the retention policy you set.