Home > Articles > Programming > Java

Java Reference Guide

Hosted by

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Maven Reporting Plug-ins, Part 1: Static Analysis Tools

Last updated Mar 14, 2003.

As Java has evolved over the past 13 years, more tools have been developed to help you analyze your Java code. These tools come in many shapes and sizes, but I like to group them into the following four categories:

  • Static Analysis Tools
  • Coverage Analysis Tools
  • Stylistic Analysis Tools
  • Performance Analysis Tools

Static analysis tools look for things like sections of your code that you might have copied-and-pasted, misuses of try/catch blocks, dead or wasteful code, code that can be identified programmatically as “buggy,” or simply report on the code’s complexity and reusability. Coverage tools identify the percentage of packages, classes, methods, and lines of code that your test cases are exercising, which can be indicative of the effectiveness of your testing strategy. Stylistic analysis tools compare your source code against standards and report any deviations from the standard. Performance analysis tools capture the response time and/or memory usage of your code which can be used to identify problematic code in your application.

But with all of these analysis tools comes challenges: how do you choose the right ones and how do you configure them to analyze your code. Fortunately for Maven users, the majority of the analysis tools are available as Maven plug-ins, so using them is as simple as adding them to the reporting section of your POM file. As far as choosing which ones to use, that’s the easy part: configure Maven to generate the reports for all of them and keep the ones that you think add value.

In this section I review several of the major analysis tools and show you how to add them to your Maven project. My review of each tool is very cursory as I could probably spend more than an entire article on each tool, but I provide an overview of what each tool does, describe how to configure its Maven plug-in, and point you to the project website where you can find more information.

Before we dive into the plug-ins themselves, let’s review the Maven mechanism that we’ll employ to invoke the plug-ins. Maven provides support for executing a series of reporting plug-ins whenever a project’s web site is generated (remember executing mvn site:site in the last update?) You need to define a reporting node in your POM file that has a list of plug-ins:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  ...

  <build>
    ...
  </build>

  <reporting>
    <plugins>
      <plugin>
        ...
      </plugin>
      <plugin>
        ...
      </plugin>
      ...
    </plugins>
  </reporting>

  <dependencies>
    <dependency>
      ...
    </dependency>
    ...
  </dependencies>
</project>

The <reporting> node controls the reports that Maven generates when the project’s web site is generated. It has a <plugins> node that contains a list of <plugin> nodes that contain plug-ins that generate reports. The sections that follow specify some of the plug-ins that you can add to your POM file to analyze your code.

PMD

PMD is a static analysis tool that scans your Java source code for problems such as the following (extracted from their web site):

  • Possible bugs: Empty try/catch/finally/switch statements
  • Dead code: Unused local variables, parameters and private methods
  • Suboptimal code: Wasteful String/StringBuffer usage
  • Overcomplicated expressions: Unnecessary if statements, for loops that could be while loops
  • Duplicate code: copied/pasted code means copied/pasted bugs

But more than simply supporting the aforementioned rules, PMD provides a platform for you, as well as other technologists, to develop rule sets. In other words, PMD is a platform for executing rules to analyze your source code.

The PMD plug-in can be executed by adding the following plug-in node to your reporting plug-ins:

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-pmd-plugin</artifactId>
        <version>2.4</version>
        <configuration>
        </configuration>
</plugin>

The configuration element controls custom behaviors that you would like the plug-in to perform. The most common option that I include is support for Java source greater than the default of 1.4, for 1.6 add the following to the configuration section:

<targetJdk>1.6</targetJdk>

Additionally you can include lists of files to exclude from the analysis by including <excludes> or <excludeRoots> nodes, for example:

<excludes>
  <exclude>**/*Bean.java</exclude>
  <exclude>**/generated/*.java</exclude>
</excludes>
<excludeRoots>
  <excludeRoot>target/generated-sources/stubs</excludeRoot>
</excludeRoots>

Finally, if you open the PMD JAR file, you’ll notice that there is a rulesets folder in it that contains a set of XML files that define the various rule sets that you asked PMD to use when analyzing your code. If you do not specify what rule sets to use, PMD defaults to using three: basic, imports, and unused code. But there are a couple dozen additional rulesets that you might consider. You can add rulesets as follows:

<rulesets>
  <ruleset>/rulesets/basic.xml</ruleset>
  <ruleset>/rulesets/imports.xml</ruleset>
  <ruleset>/rulesets/unusedcode.xml</ruleset>
  <ruleset>/rulesets/braces.xml</ruleset>
</rulesets>

The first three in the example are the three included by default and I added the “braces” rules which include rules that check to make sure that if, if/else, while, and for statements must use braces. You can read about all of the rules here and then add them in by adding one of the following XML files to your ruleset list (and the “/rulesets/” prefix is resolved to the JAR file that is automatically downloaded by Maven):

/rulesets/android.xml
/rulesets/basic-jsf.xml
/rulesets/basic-jsp.xml
/rulesets/basic.xml
/rulesets/braces.xml
/rulesets/clone.xml
/rulesets/codesize.xml
/rulesets/controversial.xml
/rulesets/coupling.xml
/rulesets/design.xml
/rulesets/favorites.xml
/rulesets/finalizers.xml
/rulesets/imports.xml
/rulesets/internal/all-java.xml
/rulesets/internal/dogfood.xml
/rulesets/j2ee.xml
/rulesets/javabeans.xml
/rulesets/junit.xml
/rulesets/logging-jakarta-commons.xml
/rulesets/logging-java.xml
/rulesets/migrating.xml
/rulesets/migrating_to_13.xml
/rulesets/migrating_to_14.xml
/rulesets/migrating_to_15.xml
/rulesets/migrating_to_junit4.xml
/rulesets/naming.xml
/rulesets/optimizations.xml
/rulesets/scratchpad.xml
/rulesets/strictexception.xml
/rulesets/strings.xml
/rulesets/sunsecure.xml
/rulesets/typeresolution.xml
/rulesets/unusedcode.xml

The following link defines all of the configuration options that are available for the plug-in as well as the default values if you do not specify any:

http://maven.apache.org/plugins/maven-pmd-plugin/pmd-mojo.html

FindBugs

FindBugs is another static code analysis tool that looks for common bugs in Java source code. Similar to PMD, FindBugs provides a plug-in architecture into which anyone can write “bug detectors” to identify bug patterns. Unlike PMD, FindBugs does not look at Java source code, but rather looks at Java bytecode. The benefit to using bytecode is that FindBugs does not need access to source code in order to detect bugs, so you can analyze code that you have not written, but the drawback is that it can generate false warnings, which are warnings that do not indicate real errors. The FindBugs team claims that the rate of false warnings is less than 50% in practice.

FindBugs can be added with the following plug-in”

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>findbugs-maven-plugin</artifactId>
  <version>2.0.1</version>
  <configuration>
  </configuration>
</plugin>

And then there are a plethora of configuration options that you can read about at the FindBugs Maven plug-in web page.

Configuration options can be found in the findbugs:findbugs task description at the following URL:

http://mojo.codehaus.org/findbugs-maven-plugin/2.2-SNAPSHOT/findbugs-mojo.html

The two most important options are probably effort, which tells FindBugs how much effort to expend in analyzing the code, and threshold, which tells FindBugs the minimum bug severity to report. The effort can be defined to be “Min,” “Default,” and “Max” and the threshold can be defined to be “High,” “Default,” “Low,” “Ignore,” and “Exp” (for experimental.) Setting the effort to “Max” will cause FindBugs to identify more potential issues.

JDepend

JDepend is a static analysis tool that parses Java source code and generates design quality metrics for each Java package in your application. It focuses on measuring the quality of the design of your code based on extensibility, reusability, and maintainability. It reports the following metrics about each package in your application (I extracted the following text directly from their web site because I did not want to confuse any of the complexity of metric definitions):

  • Number of Classes and Interfaces: The number of concrete and abstract classes (and interfaces) in the package is an indicator of the extensibility of the package.
  • Afferent Couplings (Ca): The number of other packages that depend upon classes within the package is an indicator of the package's responsibility.
  • Efferent Couplings (Ce): The number of other packages that the classes in the package depend upon is an indicator of the package's independence.
  • Abstractness (A): The ratio of the number of abstract classes (and interfaces) in the analyzed package to the total number of classes in the analyzed package. The range for this metric is 0 to 1, with A=0 indicating a completely concrete package and A=1 indicating a completely abstract package.
  • Instability (I): The ratio of efferent coupling (Ce) to total coupling (Ce + Ca) such that I = Ce / (Ce + Ca). This metric is an indicator of the package's resilience to change. The range for this metric is 0 to 1, with I=0 indicating a completely stable package and I=1 indicating a completely instable package.
  • Distance from the Main Sequence (D): The perpendicular distance of a package from the idealized line A + I = 1. This metric is an indicator of the package's balance between abstractness and stability. A package squarely on the main sequence is optimally balanced with respect to its abstractness and stability. Ideal packages are either completely abstract and stable (x=0, y=1) or completely concrete and instable (x=1, y=0). The range for this metric is 0 to 1, with D=0 indicating a package that is coincident with the main sequence and D=1 indicating a package that is as far from the main sequence as possible.
  • Package Dependency Cycles: Package dependency cycles are reported along with the hierarchical paths of packages participating in package dependency cycles.

JDepend can be added to your list of reporting plug-ins as follows:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>jdepend-maven-plugin</artifactId>
</plugin>

In short, by analyzing the interdependencies between your classes and classes in different packages in your, JDepend can compute a measurement of the complexity of your code that you can use as an indication about how well it is designed.

Taglist

Taglist is a static code analysis tool that parses your source code looking for specific tags, such as @todo and //TODO. You can specify any tags that you want to detect, which will be reported as a count on a per-class basis. Taglist is far less complex that PMD and FindBugs, but serves a big purpose nonetheless. You can add it to your

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>taglist-maven-plugin</artifactId>
  <version>2.3</version>
  <configuration>
    <tags>
      <tag>TODO</tag>
      <tag>&lt;todo</tag>
      <tag>FIXME</tag>
      <tag>DOCUMENT_ME</tag>
      <tag>NOT_YET_DOCUMENTED</tag>
    </tags>
  </configuration>
</plugin>

The tags are optional and will default to “@todo” an “TODO,” but you can add more as needed. It will find matches based on the tags it identifies that follow a comment identifier and are followed by some kind of descriptive text. The example in the documentation illustrates the rules more clearly.