Modified javac That Processes Annotations on Local Variables

Hi everyone!

This is my first post here, so if I'm doing something wrong, please let me know and have mercy with me. But I do think I have something to share that you may find interesting: Using material available from Sun under the Java Research License (JRL), I have created a modified version of the javac compiler (javac 1.5.0_06), which I call LAPT-javac, that encodes annotations on local variables into the class files it compiles.

Pre-compiled binaries, the source code, and other useful information is available from the project website at

http://www.cs.rice.edu/~mgricken/research/laptjavac

Please note that you have to accept the terms of the JRL before you can use the files I provide.

Some background information may be useful: Java 5.0 introduced annotations, meta-data that can be attached to other parts of the program. Annotations may target other annotation types, packages, types, constructors, methods, fields (including enum constants), parameters, local variables, or any combination of the above. Depending on their retention policy, annotations may be accessible in the source code only using the apt Annotation Processing Tool (SOURCE retention); they may be encoded in the class file but remain invisible at runtime (CLASS retention); or they may be accessible at runtime using reflection (RUNTIME retention).

Unfortunately, both javac and apt completely ignore local annotations on local variables. In accordance with the grammar, they do not signal a syntax error, but annotations on local variables are neither accessible in the source or class files nor at runtime! In effect, an annotation on a local variable

void someMethod() {
  // ...
  @SomeAnnotation int myLocal = 123;
  // ...
}

behaves exactly the same as if it were written like this:

void someMethod() {
  // ...
  /* @SomeAnnotation */ int myLocal = 123;
  // ...
}

Annotations on local variables are comments, and comments only. A while ago, I realized that another project I am working on could tremendously benefit if I could at least access annotations on local variables in the class files. So I decided to take a look at the javac source code released under the JRL.

To my delight, I found that annotations on local variables were being parsed correctly, and all the information was available all through the very last stage, writing the class files. My change involved only four files (ClassWriter.java, ClassReader.java, Code.java and Name.java) and about 100 lines.

On the project website linked above, I am making available a modified version of the javac compiler (javac 1.5.0_06), LAPT-javac, that encodes annotations on local variables in the class file. I also specify the format for two new, non-standard attributes, RuntimeVisibleLocalVariableAnnotations and RuntimeInvisibleLocalVariableAnnotations, on methods and constructors that closely mirror the format of the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes that Sun introduced with Java 5.0.

To use LAPT-javac, please download the LAPT-javac binaries file and execute it using Java 5.0:

java -jar laptjavac.jar <parameters>

where <parameters> matches the parameters on the javac command line you would normally use.

I have to admit that what I currently provide may not be very useful to most of you. Even though I encode annotations on local variables with RUNTIME retention in the class files, the original Java 5.0 reflection API is not be able to process these annotations, and I do not currently provide a modified reflection API. So unless you are directly processing class files on a binary/bytecode level like I am for my other project, you are probably not going to get anything out of LAPT-javac. In effect, right now only CLASS retention works as it should.

However, I have some experience with writing libraries that can be put on the Java bootclasspath, and I think I will be able to provide an enhanced reflection library that allows programmers to query annotations on local variables at runtime, just like it can already be done for method parameters. From what I know, apt uses javac's parser, and I know that parser reads annotations on local variables just fine, so an enhanced version of apt is definitely possible too (though less interesting to me personally). My hope is that eventually Sun will incorporate my changes or something similar into standard Java. I truly believe annotations on local variables can be very useful, as it really opens the door for usage-site annotations as opposed to definition-site ones.

I am very much looking forward to hearing your comments. Thank you for your time and interest.

Mathias Ricken
Graduate Student
Rice University
Computer Science

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

upcoming Java feature

Random thought, I don't know enough about it, but perhaps the upcoming pluggable annotations stuff would let you get in there and do what you need more easily?

Re: upcoming Java feature

Hi!

Thanks for your comment and for the pointer to JSR 269. I wasn't aware of that one before, so I guess there's yet another JSR that I need to track ;)

I looked at the Early Draft, and it looks like it supports a slightly extended annotation syntax as compared to Java 5.0 and provides a vastly improved support infrastructure that pulls apt into the standard API and extends it.

There are references to annotations on local variables, but I'm not exactly sure we can rely on that. After all, you can annotate local variables in Java 5.0, and the API provides the ElementType.LOCAL_VARIABLE enum value to control if an annotation can be applied to a local variable, yet the Java 5.0 compiler and apt completely ignore them.

Another reader also asked if I was aware of the Javari project at MIT and if what they were doing was similar to what I am doing. I have looked at Javari, and even though it's not even the primary focus of that exciting project, they specify an extended syntax for annotations that allows you to annotate pretty much anything in a Java program. So what they are doing is way more compli cated and extensive than what I did. I just made the Java 5.0 compiler work the way I thought it should work, given the Java 5.0 language.

There was a very encouraging paragraph on the Javari website: Apparently, Sun has agreed to extend annotations (and hopefully the way they can be processed) in Java 7.0; until then, the Javari team will provide a modified javac that supports the 7.0 syntax.

That's great, for two reasonsL: At least by the time Java 7.0 comes around, my hack should be unnecessary. And with Java 7.0 (and the Javari modification before that), we'll get extended annotations. However, Java 7.0 is still very far away, and at least from what I can tell, the Javari modification is not yet available.

Until then, I'm hoping that my hack will be useful to someone (it is useful to me) and that maybe Sun will notice how easy it was to do, so perhaps it will get rolled into 6.0 already? I know those chances are slim, but one can dream... ;)

Thanks again for your comments and question. If you have any other questions or comments, please let me know, either here or by sending me an email (contact information is on the project website).

I'm looking forward to hearing from you, and I will keep everyone posted about improving (=hacking) the reflection API and apt.