Summary
The newly proposed JSR 305, "Annotations for Java Software Defect Detection," aims to define annotations that help static analysis tools detect bugs more accurately. Spec lead Bill Pugh spoke to Artima about his new JSR.
Advertisement
The newly proposed JSR 305, Annotations for Java Software Defect Detection," aims to standardize defect-related annotations that tools such as FindBugs or IntelliJ's IDEA already provide. The JSR is led by Bill Pugh, of FindBugs' fame, who told Artima that such annotations assist static analysis tools to infer more about a developer's intentions:
In some cases, a tool can try to infer things such as whether a parameter is allowed to be null. But annotations, or some other developer-supplied information, is often far more effective. [The goal is] to come up with some standard annotations, such as @NonNull, that can be applied to Java programs to assist tools that detect software defects.
One of the annotations that FindBugs uses is @CheckReturnValue. This annotation is used for methods such as String.toLowerCase(), and indicates that invoking the method and ignoring the return value is a likely programming error. This annotation would be very hard to infer automatically.
Annotations like this are already in use by tools such as FindBugs and IntelliJ, but each is defined in its own package and sometimes with different annotations names. Developers are hesitant to invest time in providing annotations if they don't know that their annotations will be portable across tools. The annotations defined in JSR 305 will standardize the package naming, and will be applied using the existing annotations capabilities introduced in Java 5. They may also utilize any additional annotation capabilities introduced in Java SE 7.
These annotations also serve as documentation for developers and serve to help assign blame: if a static analysis tool determines that class A could pass a null value to a parameter of a method in class B that is guaranteed to dereference it, whose mistake is it, and which class should be changed? This can be a particular problem if classes A and B are maintained by different development teams: the bug isn't clearly the responsibility of any one team. If the method has an annotation that the parameter must be non-null, then clearly class A is erroneous and needs to be fixed.
In addition to documenting a developer's intentions and assisting static code analysis, defect-related annotations can also result in more secure code. Taint annotations, for instance, allow tools to check for code that allows possible SQL injection or cross-site scripting, according to Pugh:
Tainted data is any untrusted data. For example, a web application should treat the value returned by ServletRequest.getParameter() as untrusted or tainted. A String used to form an SQL query must be trusted or untainted. Static or dynamic analysis tools can check to see if a tainted value is used to compute a value that needs to be untainted. Typically, you will also designate some methods that can convert tainted to untainted data—detainting methods—via some kind of a white-list or black-list approach, or by escaping meta-characters.
Untrusted data goes beyond just SQL injection. Cross site scripting and lots of other problems can arise. Since Java doesn't have to worry about buffer overruns, improper use of untrusted or tainted data is probably one of the biggest security issues in Java.
Another proposed set of JSR 305 annotations will related to ensuring the proper handling of concurrency:
One starting point is the annotations used in Java Concurrency in Practice [by Brian Goetz]. This will allow, for example, marking classes as ThreadSafe or NotThreadSafe, and allow you to specify that a particular field should be accessed while holding a particular lock.
The JSR 305 proposal outlines the following types of defect-related annotations:
Nullness annotations (e.g., @NonNull and @CheckForNull). Both FindBugs and IntelliJ already support their own versions of nullness annotations.
Check return value annotation (e.g., String.toLowerCase())
Taint annotations. These check for errors such as SQL injection and cross-site scripting.
Concurrency. Help statically detect concurrency errors.
Internationalization annotations, such as @NonNls or @Nls, indicating values that either are or are not natural language strings that need to be localized for different locations. These annotations are currently used by IntelliJ.
A paper by Pugh and his collaborators at the University or Maryland, College Park, (Evaluating and Tuning a Static Analysis to Find Null Pointer Bugs [PDF document], describes in greater detail the limitations static analysis tools face in the absence of defect-related annotations.
What are the most common defects in your code that currently slip by static analysis tools?