September/October 2008
IEEE SotwarE
23
FindBugs in practice
In its current orm, FindBugs recognizes more than300 programming mistakes and dubious coding id-ioms that it can identiy using simple analysis tech-niques. FindBugs also uses more sophisticated anal-ysis techniques, devised to help eectively identiycertain issues—such as dereerencing o null point-ers—that occur requently enough to warrant theirdevelopment. Unlike some other tools designed toprovide security guarantees, FindBugs doesn’t tryto identiy all deects in a particular category orprove that sotware doesn’t contain a particular de-ect. Rather, it’s designed to eectively identiy low-hanging ruit—to cheaply detect deects we believedevelopers will want to review and remedy.Many developers use FindBugs ad hoc, and agrowing number o projects and companies areintegrating it into their standard build and testingsystems. Google has incorporated FindBugs into itsstandard testing and code-review process and hasxed more than 1,000 issues in its internal codebase that FindBugs has identied.
Defects in real code
To appreciate static analysis or deect detectionin general, and FindBugs in particular, it helps tobe amiliar with some sample deects ound in realcode. Let’s look at some examples rom Sun’s JDK1.6.0 implementation, which also are representativeo code seen elsewhere.One unexpectedly common deect is the in-nite recursive loop—that is, a unction that alwaysreturns the result o invoking itsel. We originallyextended FindBugs to look or this deect becausesome reshman at the University o Marylandhad trouble understanding how Java constructorsworked. When we ran it against build 13 o Sun’s JDK 1.6, we ound ve innite recursive loops,including
public String foundType() {return this.foundType();}
This code should have been a getter method orthe eld
foundType
, but the extra parenthesis meansit always recursively calls itsel until the stack over-fows. Various mistakes lead to innite recursiveloops, but the same simple techniques can detectthem all. Google has ound and xed more than 70innite recursive loops in their code base, and theyoccur surprisingly requently in other code baseswe’ve examined.Another common bug pattern is when sotwareinvokes a method but ignores its return value, de-spite the act that doing so makes no sense. An ex-ample is the statement
s.toLowerCase()
, where
s
is a
String
.Because
Strings
in Java are immutable, the
toLowerCase()
method has no eect on the String it’s invoked on,but rather returns a new
String
. The developer prob-ably intended to write
s = s.toLowerCase()
. Another ex-ample is when a developer creates an exception butorgets to throw it:
try { ... }catch (IOException e) {new SAXException(....);}
FindBugs uses an intraprocedural datafow anal-ysis to identiy places in which the code could dere-erence a null pointer.
5,7
Although developers mightneed to examine dozens o lines to understand somedeects reported by FindBugs, most can be under-stood by examining only a ew lines o code. Onecommon case is using the wrong relational or Bool-ean operation, as in a test to see whether
(name != null|| name.length > 0)
. Java evaluates the
&&
and
||
opera-tors using short-circuit evaluation: the right-handside is evaluated only i needed in order to determinethe expression’s value. In this case, Java will evalu-ate the expression
name.length
only when
name
is null,leading to a null pointer exception. The code wouldbe correct i it had used
&&
rather than
||
. FindBugsalso identies situations in which the code checksa value or null in some places and unconditionallydereerences it in others. The ollowing code, or ex-ample, checks the variable
g
to see i it’s null, but i it is null, the next statement will always deerence it,resulting in a null pointer exception:
if (g != null)paintScrollBars(g,colors);g.dispose();
FindBugs also perorms an intraprocedural typeanalysis that takes into account inormation rom
instanceof
tests and nds errors such as checked caststhat always throw a class cast exception. It alsonds places in which two objects guaranteed to beo unrelated types are compared or equality (orexample, where a
StringBuffer
is compared to a
String
,or the bug Figure 1 shows).Many other bug patterns exist, some coveringobscure aspects o the Java APIs and languages. Aparticular pattern might nd only one issue in sev-eral million lines o code, but collectively these
nda signicant number o issues. Examples includechecking whether a double value is equal to
Double.NaN
(nothing is equal to
Double.NaN
, not even
Double.NaN
)
FindBugsdoesn’t tryto identifyall defectsin a particularcategory.
Authorized licensed use limited to: IEEE Xplore. Downloaded on March 2, 2009 at 14:41 from IEEE Xplore. Restrictions apply.
Add a Comment