http://types.cs.washington.edu/jsr308/ seems to be talking about a set of type annotations for Java that are similar to those provided in Microsoft Visual C++ by SAL, the Standard Annotation Language.
One thing that the Java annotations have going for them over the SAL is that these annotations are going to be a part of the Java 7 standard, so it’s something that will come with the language no matter who implements it, whereas the C++ SAL extensions are specific to Microsoft. Of course, when I say “no matter who implements it”, I’m not aware of any significant currently supported implementations of Java outside of Sun, so it’s possible that such a statement is necessarily limited.
[Note that the SAL extensions can be included in C++ code that is compiled with other compilers, you just won’t see any benefit from them when using other compilers.]
What do annotations do?
As explained in the blog post that Michael Howard put out when SAL was first made available, these code annotations add something to object and function prototypes. What they add is the ability to turn run-time issues into compile-time errors.
So, for instance, a null pointer dereference, that would be an instant denial of service on your application, is trapped at compile time, because you declared in your function or class prototypes that you expect the pointer not to be null.
Adding these annotations to your code can certainly be a time-consuming task, since you have to revisit old code and add them in by had, recapturing assumptions that you had originally made about objects you reference. That in itself can be a learning experience, of course, and because you will capture a number of outstanding reliability, quality and security bugs, it’s far from being an empty investment.
What do the Java annotations capture?
The first checker that the Java annotations implement is the Nullness checker. This allows you to declare whether you are expecting a reference or value to be null or not. This generally avoids you seeing exceptions through dereferencing null.
The Interning checker prevents you from seeing poor results when comparing two objects (such as two instances of “Integer(2)”) using “==” or “!=”. Without the Interning checker, using “==” to compare two Integer variables each containing an instance of Integer(2) will produce the result ‘false’. This can cause logical processing errors, which the Interning checker will address.
The Mutability (IGJ or Javari) checker allows you to specify that an object reference should not be used to modify the contents of that object.
The Lock checker prevents locking errors by allowing you to declare that objects can only be accessed when guarded by a lock, or to declare that a function can only be called when holding a particular lock.
The Tainted checker allows you to mark an object as coming from an untrusted source (think “user”). Marking some functions as expecting Untainted data will prevent them from being fed Tainted data, and will ensure that other developers accessing such a function will call checking routines to convert the data from Tainted to Untainted before passing it to your functions.
The Linear checker prevents your code from holding more than one reference to objects marked as Linear. Since Java, like C#, likes to copy references to objects, rather than the objects themselves, this checker can prevent you from finding unexpected side-effects from objects being modified through aliases you weren’t expecting.
Further checkers appear to allow you to write your own checkers, but I haven’t got the Java programming chops to really play with these.
Should I include these annotations in my Java projects?
Definitely. Or something like them. Using annotations to define to the compiler some of the expectations you make of your code (a hyped-up interface contract, if you like) allows the compiler to check more deeply into whether those assumptions can hold true throughout your code.
My own experience of SAL-annotated code is that it has allowed me to discover some relatively subtle bugs in my programs. Or bugs that weren’t quite so subtle, but just weren’t jumping out at me.
A quick look at these Java annotations suggests that they will do the same for Java projects. Frankly, the more help you can get from these static analysis tools, the better. Analysis tools don’t catch all problems, and they aren’t a substitute for good programming, but they do provide a second check on your own assumptions that can be very useful.
Previous articles on SAL: