Improving your code
In 2014, IDRsolutions have been busy adding FindBugs tests which we run on our Java PDF library and PDF to HTML5/SVG converter. So the end of the year seems a good time to share some things we have learned about using FindBugs…
What is FindBugs?
FindBugs is a powerful, free, Open Source static analysis tool that can easily be used and integrated into Ant to provide bug-free and consistent code after every build.
It works by analysing Java byte code and checking every line against its growing database of common mistakes, dodgy code, bad practices and other more complex errors such as multithreading problems and security risks. After running, FindBugs produces an HTML error report listing all the possible mistakes and explaining the problem and what can be done to remedy it.
An Example of the Optimizations
One particular rule that FindBugs checks for under the category of performance is called “Method concatenates strings using + in a loop.” It provides a short explanation of the problem and an example of the solution.
// This is bad String s = ""; for (int i = 0; i < field.length; ++i) { s = s + field[i]; } // This is better StringBuffer buf = new StringBuffer(); for (int i = 0; i < field.length; ++i) { buf.append(field[i]); } String s = buf.toString();
The explanation for this performance drop when using the “+” to append strings in a loop is given by FindBugs. “In the first case, in each iteration, the String is converted to a StringBuilder, appended to, and converted back to a String. This can lead to a cost quadratic in the number of iterations, as the growing string is recopied in each iteration.”
It’s these kinds of small adjustments and bugs that FindBugs picks up on and gives great guidance about.
Getting FindBugs
FindBugs is available as a command line tool, ant and swing interface and has a plugin for Eclipse and NetBeans.
Downloads are available from the FindBugs download page
Integrating with Ant
FindBugs can be configured in ant to run as part of a static analysis test or during build each time as a code quality check.
Integration is simple and requires you to add the following rules to your jbuild.xml file:
<property name="findbugs.home" location="${lib.dir}/findbugs-3.0.0/" /> <taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask" />
This simply defines where FindBugs is located (findbugs.home) and defines the initial command FindBugs
<target name="findBugs" depends="jar"> <echo>[findBugs]</echo> <findbugs home="${findbugs.home}" includeFilter="findBugsRules.xml" output="html" outputFile="findbugs.html" failOnError="true"> <sourcePath path="${build.dir}/src" /> <class location="${dist.dir}/your_jar_here.jar" /> </findbugs> </target>
This defines the command and its parameters such as the path to the source you want it to scan and other self-explanatory fields such as “failOnError” and “outputFile”. I recommend you keep the HTML as it provides an easy way to view the bugs and statistics about your code. More information about the structure of the build file can be found here.
The “includeFilter” parameter utilises the feature in FindBugs to include/exclude only certain rules when testing.
Using FindBugs in NetBeans
NetBeans is available inside NetBeans general download. To configure this, in NetBeans after installing the plugin, go to Tools->Options->Editor->Hints. Choose FindBugs as the language and it should display a tree list.
Here you can tick/untick the corresponding tests you want to run. To run the inspection simply goto Source->Inspect and select the Configuration as FindBugs. However, running the test with all the rules checked will normally result in an enormous about of bugs found in your code. It’s recommended that over the course of days and weeks you slowly activate and fix the different rules while still maintaining new code with those rules.
However, this list does not naturally sync with the script list. To sync this private list with the “includeFilter” list that is used by ant you must find the private list file “global-settings.properties” for FindBugs which is normally located at “C:\…\AppData\Roaming\NetBeans\8.0\config\Preferences\org\netbeans\modules\findbugs” This file is a list of all the settings that you have selected, however to be used by ant it must first be converted to the correct XML format.
To do this we have written a small bit of code
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class FindBugsRulesConverter { public static String textInputRuleSet = "path\global-settings.properties"; public static String xmlOutputRuleSet = "findBugsRules.xml"; public static void main(String[] args){ try{ //Get writer and rewrite the file BufferedWriter xmlOutputWriter =new BufferedWriter(new FileWriter(xmlOutputRuleSet,false)); //Write first opening xml lines xmlOutputWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); xmlOutputWriter.newLine(); xmlOutputWriter.write("<FindBugsFilter>"); xmlOutputWriter.newLine(); xmlOutputWriter.write(" <Match>"); xmlOutputWriter.newLine(); //Get reader of text file BufferedReader textInputReader =new BufferedReader(new FileReader(textInputRuleSet)); String line = textInputReader.readLine(); StringBuilder list= new StringBuilder(" <Bug pattern=\""); while(line !=null){ //Only use rules set to "true" if(line.endsWith("true")) { list.append(line.substring(0, line.length()-5)).append(",\n"); } line = textInputReader.readLine(); } list.deleteCharAt(list.length()-1); list.append("\" />"); xmlOutputWriter.write(list.toString()); xmlOutputWriter.newLine(); textInputReader.close(); //Write closing xml lines xmlOutputWriter.write(" </Match>"); xmlOutputWriter.newLine(); xmlOutputWriter.write("</FindBugsFilter>"); xmlOutputWriter.close(); }catch(final IOException e) { e.printStackTrace(); } } }
This will convert the properties file into a useful XML file containing the list of rules you want to include in the test, but remember to change “textInputRuleSet” and “xmlOutputRuleSet” to match the path to the appropriate files. This now allows you to easily generate the rules that you want to test for when using an ant script to run FindBugs. This helps to produce cleaner, faster and less buggy code after every build.
I hope you’ve enjoyed our article, please let us know in the comments below.