Software
developers use a large number of tools to help them in their day to
day tasks and coding activities. Static analysis tools are most
commonly used tools which help verify the code and find potential
bugs.
The
two most popular static analysis tools for Java are PMD and FindBugs.
According to code quality tools review, 2013, FindBugs is used by
33% of the respondents and PMD is used by 23% of the respondents. It
is worthwhile to evaluate their effectiveness and find out the best
practices in using them, since these are the most commonly used
tools.
Introduction to PMD
Basic
features
PMD
is a rule based static analysis tool that works on source code
files. It comes with a set of rules, grouped into rulesets. Each rule
has the following properties:
- Priority
- Rule Set
- Rule implementation class
- Message
Priority
Rules
are also categorized as per their severity into one of five classes,
each represented by a default color:
- Blocker (red)
- Critical (cyan)
- Urgent (green)
- Important (pink)
- Warning (blue)
You
can also change the severity (and color) of a particular rule based
on user preference.
Rule
Set
Currently,
PMD supports around 33 rulesets which contain approximately 313 rules
such as:
- Basic (java): This ruleset checks agains good practices which should be followed for all Java projects.
- Basic XML: Contains a collection of good practices for XML.
- Migration: Contains rules about migrating from one JDK version to another.
- Naming: Checks against conventions for naming variables, methods and identifiers.
- Optimization: Checks against optimization best practices.
- Security Code Guidelines: These rules check against the security guidelines from Sun.
- Strict Exceptions: Check for bugs or bad code in exception handling.
PMD
also comes with its default ruleset which includes all the rules in
the Basic (java), Import Statements ruleset and Unused Code ruleset
which gives a total of 34 rules. A user can configure his own custom
ruleset borrowing rules from any or all of these rulesets. In fact, a
user can write his own rules too. The rule-ruleset association can
also be changed, for example if you believe a particular rule is more
appropriate in some other ruleset, you can add it to that ruleset.
Working
PMD
is a source code analysis tool. This makes it most appropriate for
finding problems with code style, syntax and violations of coding
standards and best practices.
- User selects the rules or rulesets based on his preferences. User runs PMD on a source file or a package(s). Alternately, PMD can also be configured to run automatically.
- PMD parses the source code and generates an abstract syntax tree of the files of the source.
- Each of the rulesets traverses the abstract syntax tree.
- Each ruleset reports all the violations it found. This data is then consolidated into a report which the user can view. PMD allows you to view this report in different formats such as CSV, XML, HTML, etc.
Use
PMD
can be used in different ways based on user's comfort:
- From the command line
- As a plugin integrated into eclipse (also as a Maven plugin)
- PMD comes with a CPD GUI (Copy Paste Detector) which finds repeated blocks of code. The minimum number of lines to consider as a block is configurable.
PMD
comes with a lot of configurable settings and features and it is
evident that user friendliness and flexibility are a key focus.
Introduction to FindBugs
FindBugs
is different since it works on byte code. FindBugs uses BCEL (Byte
Code Engineering Library) which helps it analyze java bytecode. BCEL
itself comes with a byte
code verifier named JustIce. FindBugs
can also be used to find problems in compiled classes and jar files.
FindBugs finds potential problems matching a bytecode against
different bug patterns.
There
is a bug detector defined for each bug pattern. Each bug detector has
associated with it:
- Detector Id
- Pattern
- Speed
- Category
Bug
categories
Each
bug detector finds a particular type of bug which belongs to one of
the following categories:
- Malicious code vulnerability
- Dodgy code
- Bad practice
- Correctness
- Internationalization
- Performance
- Security
- Multithreaded Correctness
- Experimental
Bug
Rank
Bugs
are ranked according to their severity as:
- Scariest (red)
- Scary (orange)
- Troubling (yellow)
- Of Concern (blue)
Confidence
level
Each
bug detector has a confidence level associated with it. This
indicates how much confidence the detector has that the bug warnings
found by it are truly bugs. You can configure at what confidence
level you want the bug detectors to show you the results. This means,
if you are nervous about the code and want FindBugs to show all
warnings, you can configure the detectors to show bugs at all
confidence levels. This configuration is applicable to the selected
bug categories only. This helps the user focus on the main aspect of
the project for e.g. You can configure FindBugs to find security
related bugs at all confidence levels. Confidence level settings can
also be used to ignore warnings at lower confidence level so as to
decrease the number of false positives reported.
Use
FindBugs
can be used as an Eclipse Plugin, GUI tool and from the command line.
The warnings detected can be reported in XML format.
What we found most interesting about the two tools
PMD:
- PMD supports a very large number rules covering broad range of bug problems.
- PMD is highly configurable and flexible. This makes it both good and bad. Good in the sense that the user can use the tool according to his comfort and requirement. However, this becomes overwhelming sometimes. We discovered, what bugs get fixed and how many false positives you get depend highly on the configurations and the users understanding of the configurations and the project.
- PMD has a easy to use rule designer interface that allows you to add your own new custom rule.
FindBugs:
- FindBugs finds lesser false positives and you can set the confidence level at which the detectors should work. This makes it less overwhelming to go through the bug warnings.
- FindBugs has a new feature that connects your bug warning reports to the Cloud.
- FindBugs also comes with its own data mining capabilities that can be used to mine bug reports over several project versions and timelines. This makes it very handy tool for fine tuning the configuration of the tool and analyzing developer mistakes over time.
Our experience with the tool
JFreeChart
- JfreeChart is an open source Java library that helps developers create a large variety of high quality charts. JfreeChart is the most popular chart library.
- It started as an open source project since 2000. Since it has been in existence for over 13 years, it is rich in version history.
- Since it is popularly used, the expectation is that most of the relevant bugs are fixed by the developers over several versions of the tool.
- We found it relatively easy to configure the project.
Approach
- We ran the tools on two versions of the tool. We selected version 1.0.0 and version 1.0.16 (latest). These versions were sufficiently apart for the major bugs to have been fixed over the versions.
- We first ran only the tools with default configurations since we believe that the default configuration must be most commonly used by developers. The default setting must find the most relevant bugs.
- Any bug that got fixed from the older versions in the newer versions, must be a true positive.
- Only classes that were present in both the versions were considered since additional classes indicate either new features or deprecation.
Running
PMD on JfreeChart
For
PMD Basic Ruleset, the results were as follows:
JFreeChart
v1.0.0
Total
warnings : 595
Total
distinct warnings : 25
Warning
|
Count
|
Avoid
unused constructor parameters such as shapesVisible.
|
1
|
Avoid
unused imports such as
org.jfree.chart.renderer.category.LevelRenderer
|
1
|
Avoid
unused method parameters such as g2.
|
1
|
Avoid
unused constructor parameters such as outlinePaint.
|
1
|
Avoid
unused method parameters such as orientation.
|
1
|
Unnecessary
use of fully qualified name java.util.Date due to existing import
java.util.Date
|
2
|
Avoid
unused constructor parameters such as linesVisible.
|
1
|
Avoid
unused local variables such as b.
|
2
|
Avoid
unused imports such as org.jfree.chart.axis.CategoryAxis
|
1
|
These
nested if statements could be combined
|
45
|
Avoid
unused local variables such as contentConstraint.
|
1
|
Avoid
unused private fields such as flag.
|
1
|
Avoid
unused constructor parameters such as outlineStroke.
|
1
|
Avoid
modifiers which are implied by the context
|
492
|
Unnecessary
use of fully qualified name java.util.ArrayList due to existing
import java.util.ArrayList
|
16
|
Unnecessary
use of fully qualified name java.awt.Color.lightGray due to
existing import java.awt.Color
|
1
|
Unnecessary
use of fully qualified name java.text.SimpleDateFormat due to
existing import java.text.SimpleDateFormat
|
1
|
Avoid
unused imports such as
org.jfree.chart.renderer.category.LayeredBarRenderer
|
2
|
Avoid
unused method parameters such as dataArea.
|
1
|
Avoid
unused imports such as org.jfree.chart.plot.CategoryPlot
|
1
|
Avoid
unused imports such as
org.jfree.data.category.DefaultCategoryDataset
|
1
|
Avoid
unused imports such as org.jfree.chart.plot.Plot
|
1
|
Ensure
you override both equals() and hashCode()
|
18
|
Avoid
unused constructor parameters such as percent.
|
1
|
Avoid
unused local variables such as image.
|
1
|
JFreeChart
v1.0.16
Total
warnings : 742
Total
distinct warnings : 21
Warning
|
Count
|
Avoid
unused method parameters such as orientation.
|
2
|
Avoid
unused method parameters such as g2.
|
1
|
Avoid
unused imports such as org.jfree.data.general.DatasetUtilities
|
6
|
Avoid
unused local variables such as datasetIdx.
|
1
|
These
nested if statements could be combined
|
65
|
Avoid
unused local variables such as section.
|
1
|
Avoid
unused private fields such as event.
|
1
|
Avoid
modifiers which are implied by the context
|
561
|
Unnecessary
use of fully qualified name java.util.ArrayList due to existing
import java.util.ArrayList
|
41
|
Avoid
unused local variables such as rect.
|
1
|
Unnecessary
use of fully qualified name java.awt.Color.lightGray due to
existing import java.awt.Color
|
1
|
Avoid
unused constructor parameters such as cloneData.
|
2
|
Unnecessary
use of fully qualified name java.text.SimpleDateFormat due to
existing import java.text.SimpleDateFormat
|
1
|
Avoid
unused constructor parameters such as labelCount.
|
1
|
Avoid
unused method parameters such as dataArea.
|
1
|
Avoid
modifying an outer loop incrementer in an inner loop for update
expression
|
2
|
Ensure
you override both equals() and hashCode()
|
50
|
Avoid
unused local variables such as description.
|
1
|
Avoid
unused local variables such as count.
|
1
|
Avoid
unused imports such as java.util.Objects
|
1
|
Avoid
unused method parameters such as ignoreThisDummyArgument.
|
1
|
What
we are looking for in this data:
- Warnings that are common to both versions, imply either:
- If their count has decreased from the previous version, the warning is important for this project. Hence, some of them were fixed. These type of warnings are recurring in this project and need to be looked at carefully.
- If the count has not decreased, it means these warnings are not correct, especially in the context of the project since the developers did not find them useful/important enough to fix them.
- Some of the “bugs” detected could be delibrate or for testing purpose, conciously placed by the developer. For example “Avoid unused method parameters such as ignoreThisDummyArgument.” These warnings need not be considered.
- Increase in warning count doesn't necessarily mean poorer quality of code. It could mean more features have been added to the code. However, warnings per kloc of code or warnings per method, need to be closely looked at.
Running
FindBugs on JFreeChart
Information
|
v1.0.0
|
v1.0.16
|
Total
bugs
|
163
|
133
|
By
Bug Rank
|
||
Scariest
|
1
|
0
|
Scary
|
38
|
15
|
Troubling
|
117
|
109
|
Of
concern
|
7
|
9
|
By
Category
|
||
Bad
Practice
|
107
|
103
|
Correctness
|
40
|
15
|
Dodgy
Code
|
8
|
10
|
Multithreaded
correctness
|
8
|
5
|
By
Confidence
|
||
High
Confidence
|
112
|
119
|
Normal
Confidence
|
21
|
44
|
What
we are looking for in this data:
- It is clearly evident that the count of most of the warnings has gone down over the next version. This implies that the particular bug category is relevant to the project. Hence, FindBugs must always be configured to detect this category of bugs for this project.
- FindBugs detector confidence levels have gone up over the versions of the project. This implies more obvious bugs are being introduced into the code.
We
plan to consolidate and derive more findings from such data. We would
like to suggest a plan for configuring rulesets/detectors which will
be most relevant for the project based on previous bug fixes. This
way one could derive maximum efficiency from the tool and also have
to look at lesser false positives.
Nachiket
V. Naik
Computer
Science
North
Carolina State University
Raleigh,
US
nvnaik@ncsu.edu
Preeti
Satoskar
Computer
Science
North
Carolina State University
Raleigh,
US
pysatosk@ncsu.edu
References
- Information about Code Quality Review, 2013: http://zeroturnaround.com/rebellabs/code-quality-tools-review-for-2013-sonar-findbugs-pmd-and-checkstyle/
- PMD rulesets: http://pmd.sourceforge.net/pmd-5.0.5/rules/index.html
- PMD rules index: http://www.ing.iac.es/~docs/external/java/pmd/rules/
- FindBugs Fact Sheet: http://findbugs.sourceforge.net/factSheet.html
- BCEL homepage: http://commons.apache.org/proper/commons-bcel/
- FindBugs homepage: http://findbugs.sourceforge.net/