Comparative FindBugs (CFB): Introduction

Findbugs is a wonderful tool that performs a static analysis of Java code, flagging lots of bugs, and with astoundingly few false alarms. If you haven't encountered it before, I'll let David Hovemeyer and William Pugh (the folks who created FindBugs) explain it to you. Go ahead and read Using FindBugs in Anger now. This page will be waiting for you when you're done.

CFB Uplands, 1952

A note about the picture: this shows Canadian Forces Base (a different kind of CFB) Uplands in 1952. This location still serves air traffic today, but is better known as Ottawa International Airport (YOW). I remember seeing the picture on display at the airport a few years ago, and found it online here with the following note: “ Darrell Larose ‎Lost Ottawa RCAF Station Uplands in 1952, aerial view shows 57 RCAF CF-86 Sabre jet fighters. The ground view shows a line of 21 CF-86's This was a staging for Operation Leap Frog to RCAF Station Grostenquin. The airbase at Uplands/Ottawa Airport was decommissioned as a base in 1996. ” I believe that this image is in the Canadian public domain, given that copyright has now expired on any photographs from 1952 that were either subject to Crown Copyright or whose copyright was owned by a corporation, and I find it hard to imagine a private individual having permission to photograph a military base. If you are the copyright holder and want this picture removed, please contact me (user cejaekl site yahoo.com).

In an ideal world, we would all run FindBugs on every Java project from its inception, and keep the count of FindBugs diagnostics at zero. (In theory, there is no difference between theory and practice. In practice, there is.)

I don't know about you folks, but I tend to end up being responsible for code bases that have been developed by other people, to other standards. I put together CFB after I ran FindBugs on some code that I had “inherited” in this way, and came up with 1025 “bugs” crying out for attention. (No, I will not tell you which code… to protect the guilty.) There are a few reasons why I couldn't bash those all into oblivion right away:

So, in this imperfect world, I opted for the imperfect solution of attempting gradual improvement over the long term, instead of a “big bang” bug bashing party. Trendy business speakers might call this approach “continuous improvement” or 改善, but I just call it pragmatic.

In short, I was resigned to having a large number of FindBugs messages in this code base for the foreseeable future. This left me with a problem, though: I wanted to leverage FindBugs to make sure that, as I introduced new code (and bug fixes), I didn't make things worse by adding code that FindBugs complained about. (The Romans had a saying for this: primum non nocere—first, do no harm.) I needed some way to identify any FindBugs diagnostic messages that were generated by code that had changed.

This is not as hard as it might seem. By running FindBugs on the code both before and after a commit to the source code repository, and then computing the difference between the two FindBugs reports, we get a list of bugs in three categories:

CFB is a tool to do just that: run FindBugs whenever commits are added to the source code repository, generate reports on the differences between runs, and (optionally) send a notification email when new “bugs” are introduced or old “bugs“ are fixed.

Installing and Using CFB

The source code for CFB is available under the GNU General Public Licence, version 3 or later.

The head-of-stream should, in general, be safe to use—I make a point of keeping it that way. You can confirm the current status by checking my Jenkins server. The code coverage report (showing which bits of the code base should really have better unit tests) is also available there, and you can even see the current result of running CFB on itself.

I don't (currently) offer precompiled packages, but building it yourself is not hard.

  1. Prerequisites:
  2. Configure paths:
  3. (Optional) Test-compile the code, and run the unit tests (includes calculating code coverage, hence the name of the script):
    $ ./cov.sh

  4. Create a FindBugs Project (.fbp) file. This specifies the following things about your project: You can create your .fbp file by launching the FindBugs GUI (${FINDBUGS_HOME}/bin/findbugs), creating a new project, and then selecting Save As... and specifying FindBugs project file as your output filetype. But you may find it easier to create it by yourself. Here's a simple example that should be self-explanatory:
        <Project projectName="CFB">
          <Jar>/home/chris/prog/cfb/bin<Jar>
          <AuxClasspathEntry>/usr/share/java/commons-cli.jar<AuxClasspathEntry>
          <AuxClasspathEntry>/usr/share/java/junit4.jar<AuxClasspathEntry>
          <AuxClasspathEntry>/usr/share/java/postgresql.jar<AuxClasspathEntry>
          <SrcDir>/home/chris/prog/cfb/prod<SrcDir>
        <Project
  5. Run CFB to do an initial analysis:
    $ ./go.sh -u dbUser -p dbPassword -d databaseName -f /path/to/your.fbp -o /where/to/write/report.html
    If you are worried about the security implications of having your database password visible in the command-line, you can specify it in your config.properties file (db.pass=dbPassword) instead.
    See net.jaekl.CFB.Config for a full list of configuration settings.
    To see a full list of command-line options, use:
    $ ./go.sh --help

  6. Continue developing your code.

  7. Re-run CFB, to generate a comparison (delta) report on the differences since you last ran it on your project:
    $ ./go.sh -u dbUser -p dbPassword -d databaseName -f /path/to/your.fbp -o /where/to/write/report.html