What is in spotbugs annotations?

NOTE This article was originally written in August 2018. As it was never posted, I have now posted it unmodified with an updated publication date.

In my current project, I am working on extending otr4j with OTRv4 support. ‘otr’, off-the-record, is a communication protocol that allows a user to establish a secure communication channel over a plain (untrusted) chat network.

Reducing distractions, allowing for focus

As part of this work, I am looking into how we can alleviate developers from the trivial kinds of inspections, mistakes, formatting issues, etc. Not necessarily that they do not have to pay any attention to these aspects. For many of these aspects, some manual inspection is needed first, or alternatively there are trade-offs to be made. For now, I am looking for any kind of support in identifying issues as well as failing the build as a way of informing the developers that there are improvements to make. This prevents quality from degrading below the threshold that the build-time analyses set. I am talking, of course, about compile-time warnings from the java compiler, extending static analysis capabilities with JSR 305, and static analysis plug-ins such as checkstyle, pmd, spotbugs (previously findbugs), animal-sniffer and others.

Now, on first impression, these may sound like annoying additions. However, it allows the developers to focus on the difficult tasks at hand, instead of getting distracted by trivialities. In addition, these build failures will happen at build-time during a maven build. It does not, however, need to bother the developers while programming, i.e. while working in the development environment itself. When the hard work is done - a final build is done before pushing the finished work to the server - that is when we start paying attention to the trivialities that still have to be fixed, if any.

A well-known approach to extending static analysis capabilities in a code-base is to annotate methods with nullability annotations. We analyzed and eradicated almost all use of null. Apart from a few exceptions, null did not offer any value. The nullability annotations allow the IDE (IntelliJ IDEA, Netbeans and Eclipse) to provide real-time feedback based on use of null. However, there are more characteristics to analyze than the use of null.

SpotBugs annotations

SpotBugs, the “spiritual successor” to findbugs, offers annotations of its own. Recently, SpotBugs stopped supporting JSR 305 annotations in its analysis. As I was investigating possibilities for more extensive analysis, I stumbled upon spotbugs-annotations. Let’s have a look at what SpotBugs annotations has to offer.

There are different kinds of annotations. We’ll go through each category.

Return-value analysis

These annotations allow you to express that there is a certain “special interest” in the return value of a method. For example, an equals method does not have any side-effects. Therefore it is important that the return value is actually checked. If it is ignored, there is no sense in calling the method.

Null-analysis

To help uncover errors regarding the abuse of possible null values, there are annotations that allow the developer to define it expectations regarding null. This will allow static analysis to evaluate the implementation of a method to ensure that all code paths exhibit the expected behavior. Similarly, it analyzes usage logic to ensure that it takes into account possible null values, or alternative does not needlessly check for null when it cannot happen.

Resources (clean-up obligations)

The concept ‘resource’ is used for any object that requires some kind of “cleaning up” after use. The most well-known examples are the file handle and the network connection. The file needs to be closed after you are done reading from it/writing to it. The network connection needs to be closed. In “lower-level” languages like C and C++, memory needed to be reserved and cleaned manually. Memory reservations, in this case, have the same characteristic.

There are other, less obvious applications, such as the cleaning of sensitive data after use. These too have this same characteristic of a resource.

Default annotations (Define default annotations for class or package to avoid repeating.)

Default annotations exist to prevent having to repeat annotations many times. The define annotations that should be expected everywhere. Therefore, it simplifies the developer’s job as you only need to annotate the exceptions to the rule.

Class-hierarchy

Then there is the category of annotations that influence the type hierarchy for a particular class. These are used to help static analysis cross over the single type-boundary.

Suppressing warnings

The annotation that is used for suppressing findbugs and SpotBugs warnings.

Deprecated annotations:

Finally, there are a few more annotations that should not be used anymore because they are deprecated. These annotations have an alternative available, so there is no need to continue using these. For example, PossiblyNull is replaced by CheckForNull.