FindBugs: make your code better with Resource Management Annotations

FindBugs is a nice tool that helps finding problematic areas in your code. But, not only that: it provides several annotations that you can add to your own code to make it easier to use in a robust way, by helping FindBugs pinpoint potential problems when other programmers use it.

Several of these annotations are intended to help catch a very common error with resource handling: forgetting to call cleanup methods, such as the proverbial close. Too bad that these annotations are not documented in the FindBugs manual: I hope this post contributes to make using them easier.

Diagnosing missing cleanup

Sometimes you create classes that handle expensive resources. For those classes, you should probably perform cleanup as soon as you have finished using the resource, exactly the same way you need to call a cleanup method for a JDBC Connection, a Stream, sockets, etc.

There is a hidden gem in FindBugs that allows you to annotate your own resource classes so that, if you forget to call their cleanup method, it will flag the mistake.

Note that, to use these annotations, you need to add a pair of jars FindBugs provides: annotations.jar and jsr305.jar. However, these jars need not be redistributed, they are used at compile time only.

The following class, ResourceClass, uses the @CleanupObligation, @CreatesObligation and @DischargesObligation annotations in FindBugs to provide that functionality:

@edu.umd.cs.findbugs.annotations.CleanupObligation
public static class ResourceClass {
  @edu.umd.cs.findbugs.annotations.CreatesObligation()
  public ResourceClass() {
    // Do nothing: just for illustrative purposes
  }

  @edu.umd.cs.findbugs.annotations.DischargesObligation
  public void doCleanup() {
    // Do nothing: just for illustrative purposes
  }
}

First of all, you annotate the resource class with the @CleanupObligation annotation. This makes it clear that the class manages a resource that will need to be release.

Secondly, you need to specify which is/are the method(s) or constructor(s) that acquire the resource: you just annotate them with @CreatesObligation.

Thirdly, you need to specify which is/are the method(s) that perform cleanup, using the @DischargesObligation annotation. That’s it!

Let’s see what happens when FindBugs sees code that acquires the resource but forgets to perform cleanup, such as this:

public void handleResourceForgettingCleanup() {
  // FindBugs warning
  // Method ...handleResourceForgettingCleanup() may fail to clean up...
  new ResourceClass();
}

This sample code acquires a resource, as it invokes the constructor marked with @CreatesObligation, but it forgets to call the corresponding cleanup method –doCleanup, marked with @DischargesObligation. When checking this code, FindBugs pinpoints the issue as follows (in Eclipse):

FindBugs Resource Handling Annotations Error Message

Neat, huh? Once the code is corrected, as shown in the following code, FindBugs will not complain anymore:

public void handleResourceWithCleanup() {
  ResourceClass resource = new ResourceClass();
  try {
    // Just use resource in some way to please our very demanding compiler
    resource.toString();
  }
  finally {
    resource.doCleanup();
  }
}

This is a very nice thing, but apparently FindBugs does not perform inter-procedural analysis for this, so this will not be diagnosed correctly in a complex scenario.

No problem. I think that the annotations would be useful even if they were used to document only. The fact that they help FindBugs diagnose wrong code nine out of ten times just makes it better.

But I’ve got a false positive!

Well, yes, false positives can happen: FindBugs is good, but not perfect.

The simplest solution is to add a @SuppressWarnings annotation to make FindBugs ignore the issue. I will not discuss that annotation here, as it deservers more time than what I have available right now.

Be careful, for there is a FindBugs specific @SuppressWarnings annotation, which is different from @java.lang.SuppressWarnings: don’t mix them!

Tool and library versions

The FindBugs version we have used for this article is 1.3.9, with the corresponding plugin running in Eclipse 3.3.0.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s