Home » Software Development » Using FindBugs to produce substantially less buggy code

About Byron Kiourtzoglou

Byron Kiourtzoglou
Byron is a master software engineer working in the IT and Telecom domains. He is an applications developer in a wide variety of applications/services. He is currently acting as the team leader and technical architect for a proprietary service creation and integration platform for both the IT and Telecom industries in addition to a in-house big data real-time analytics solution. He is always fascinated by SOA, middleware services and mobile development. Byron is co-founder and Executive Editor at Java Code Geeks.

Using FindBugs to produce substantially less buggy code

Some time ago a user of Java-monitor, the forum of our JCG partner, Kees Jan, spotted that his system was forcing a large number of full Garbage Collections despite the fact that the overall memory utilization was low. A rough estimation for the cause of the problem suggested a potential call to System.gc() performed by one of the libraries in use. Lets see what our partner has to say about clarifying similar issues in order to produce substantially less buggy code.

… It did occur to me that there is a tool that could have helped with the System.gc() issue. It is aptly named FindBugs. Actually, there are several (PMD and CheckStyle being other, similar tools), but FindBugs is nice because you don’t actually need the application’s source code to check it for bugs. All you need are the JAR files and/or class files. Another great feature is that each report is documented very well. You don’t just get vague warnings that you sort-of give up on after a few minutes, but you can find an explanation for each warning on-line.

Here is a sample output of FindBugs, when you would run it against Java-monitor’s probe.

$ findbugs -textui -effort:max java-monitor-probes/build/WEB-INF/classes
The following classes needed for analysis were missing:
Missing classes: 7

From this report you can see that FindBugs cannot find any issues with the code itself. There are some classes that the code depends on. These were not included in the analysis. Since these are all Sun-provided classes I presume them to be bugfree. *cough*

Anyway. Let’s make the analysis a bit more juicy. Here is the output when running FindBugs against the well-known MySQL JDBC driver. I’m sure that many of you use it in production today. This code produces significantly more results and FindBugs takes a while to analyse the whole package. I have shown only a few lines of the 154 warnings.

$ findbugs -textui -effort:max mysql-connector-java-5.1.5-bin.jar 
H C NP: Method call in com.mysql.jdbc.profiler.ProfilerEvent.pack() passes null for unconditionally dereferenced parameter of writeBytes(byte[], byte[], int)  Method invoked at ProfilerEvent.java:[line 375]
M D NP: Possible null pointer dereference of s1 on path that might be infeasible in com.mysql.jdbc.ConnectionImpl.nullSafeCompare(String, String)  Dereferenced at ConnectionImpl.java:[line 341]
M C NP: Method call in com.mysql.jdbc.DatabaseMetaData.getInstance(ConnectionImpl, String) passes null for unconditionally dereferenced parameter of new DatabaseMetaData(ConnectionImpl, String)  Method invoked at DatabaseMetaData.java:[line 632]
H S SQL: Method com.mysql.jdbc.DatabaseMetaData.getColumnPrivileges(String, String, String, String) passes a nonconstant String to an execute method on an SQL statement  At DatabaseMetaData.java:[line 2156]
H S SQL: Method com.mysql.jdbc.DatabaseMetaData.getTablePrivileges(String, String, String) passes a nonconstant String to an execute method on an SQL statement  At DatabaseMetaData.java:[line 4638]
M S SQL: Method com.mysql.jdbc.ConnectionImpl.setSessionVariables() passes a nonconstant String to an execute method on an SQL statement  At ConnectionImpl.java:[line 5074]
M M IS: Inconsistent synchronization of com.mysql.jdbc.CallableStatement.outputParameterResults; locked 50% of time  Unsynchronized access at CallableStatement.java:[line 1948]
M M IS: Inconsistent synchronization of com.mysql.jdbc.StatementImpl.wasCancelledByTimeout; locked 83% of time  Unsynchronized access at PreparedStatement.java:[line 1756]
Warnings generated: 154

Learning to read the output of FindBugs takes a little time. What I do is just work through a certain error or warning when I’m bored or frustrated with the code that I should be writing. It’s my procrastination work. :-)

I have only picked out the things that as a developer strike me as problematic: “passes null for unconditionally dereferenced parameter”. Eek. NullPointerException anyone? Of course, this could well be test code, or even unused code that is still under development. How about this: “passes a nonconstant String to an execute method on an SQL statement”. Hmm. If left unchecked, this could be a vector for an SQL injection vulnerability.

I said earlier that FindBugs does not require you to have access to the source code of an application to find bugs in it. Just for laughs, let’s have a look at one of the cornerstones of our Java EE application servers: The Oracle JDBC driver.

$ findbugs -textui -effort:max ojdbc6.jar
M B Dm: oracle.sql.ConverterArchive.openArchiveforRead() invokes System.exit(...), which shuts down the entire virtual machine  At ConverterArchive.java:[line 375]
M B Dm: oracle.sql.ConverterArchive.closeArchiveforRead() invokes System.exit(...), which shuts down the entire virtual machine  At ConverterArchive.java:[line 390]
M B ES: Comparison of String objects using == or != in oracle.jdbc.connector.OracleConnectionRequestInfo.equals(Object)   At OracleConnectionRequestInfo.java:[line 104]
H C IL: There is an apparent infinite recursive loop in oracle.jdbc.rowset.OracleCachedRowSet.updateBlob(int, InputStream, long)  At OracleCachedRowSet.java:[line 6365]
H C IL: There is an apparent infinite recursive loop in oracle.jdbc.rowset.OracleCachedRowSet.updateClob(int, Reader, long)  At OracleCachedRowSet.java:[line 6445]
H C IL: There is an apparent infinite recursive loop in oracle.jdbc.rowset.OracleCachedRowSet.updateNClob(int, Reader, long)  At OracleCachedRowSet.java:[line 6535]
Warnings generated: 1028

That driver produces no less than 1028 warnings. Wow. I’m not suggesting that the Oracle JDBC driver is actually a bad piece of code. I just find that it smells a little. :-) Oracle’s developers might want to have a crack at resolving the findbugs-reported warnings. There are many little performance and stability suggestions in there.

And yes: findbugs checks for uses of System.gc().

PS. Please be aware that I used FindBugs 1.3.7. This version of FindBugs has a bug that causes it to generate false positives for cleaning up database resources.

PPS. Who am I kidding: I do think that the Oracle driver is bad. Infinite loops? System.exit()? Please.

Always help a … coder in need ;-)


Related Articles:

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

and many more ....


One comment

Leave a Reply

Your email address will not be published. Required fields are marked *


Want to take your Java Skills to the next level?
Grab our programming books for FREE!
  • Save time by leveraging our field-tested solutions to common problems.
  • The books cover a wide range of topics, from JPA and JUnit, to JMeter and Android.
  • Each book comes as a standalone guide (with source code provided), so that you use it as reference.
Last Step ...

Where should we send the free eBooks?

Good Work!
To download the books, please verify your email address by following the instructions found on the email we just sent you.