PMD (Java Source Code Analyzer)
Table of Contents
1. PMD 简介
PMD 是一个代码静态分析工具(主要针对 Java 语言,它也支持其它语言),可以发现代码中的一些问题,比如:
- 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
PMD 使用 JavaCC 对 java, plsql, jsp, velocity 等程序进行语法分析。
PMD 可以和 Eclipse,IntelliJ 等等工具进行集成,参考:https://pmd.github.io/pmd-5.5.0/usage/integrations.html
注:PMD 这三个字母没有什么含义,其作者说仅仅是由于它们读起来朗朗上口,你可以认为它是“Pretty Much Done”或者“Project Mess Detector”等的缩写。参考:https://pmd.github.io/pmd-5.5.0/overview/meaning.html
2. 在 maven 工程中使用 PMD
第一步,在工程的 pom.xml 文件中,加入下面内容:
<project> ... <reporting> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> <version>3.8</version> </plugin> </plugins> </reporting> ... </project>
第二步,执行下面命令:
$ mvn pmd:pmd
第三步,查看报告。
上面命令执行结束后,会在 target 目录中生成报告文件。
$ find target/ target/ target/java-empty.xml target/site target/site/pmd.html target/pmd.xml target/java-basic.xml target/java-unnecessary.xml target/java-unusedcode.xml target/java-imports.xml
直接用浏览器打开文件“target/site/pmd.html”即可。
参考:
http://maven.apache.org/plugins/maven-pmd-plugin/usage.html
https://pmd.github.io/pmd-5.7.0/usage/mvn-plugin.html
2.1. 和 JXR 集成
在 PMD 生成的报告中,会显示发现问题的行号,但不能点击。使用工具 JXR 可以建立交互引用,这样点击行号就可以直接查看到那行的源代码了。
在工程 pom.xml 文件中加入下面内容即可:
<project> ... <reporting> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> <version>3.8</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jxr-plugin</artifactId> <version>2.5</version> </plugin> </plugins> </reporting> ... </project>
执行下面命令生成可交叉引用的 html 文件及 pmd 报告:
$ mvn jxr:jxr # 首先,使用jxr生成交叉引用的html文件 $ mvn pmd:pmd # 然后,生成pmd报告
上面命令可合并为 mvn jxr:jxr pmd:pmd
。
3. PMD 报告实例
假设 maven 工程中有下面 Java 代码:
1: package com.mycompany.app; 2: 3: import java.io.BufferedReader; 4: import java.io.IOException; 5: import java.nio.file.Files; 6: 7: public class App { 8: public static enum WeekDay { 9: SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY 10: }; 11: 12: public static void main( String[] args ) { 13: System.out.println( "Hello World!" ); 14: 15: try (BufferedReader reader = Files.newBufferedReader(Files.createTempFile(null, ".txt"))) { 16: String line = null; 17: while ((line = reader.readLine()) != null) { 18: System.out.println(line); 19: } 20: } catch (IOException x) { 21: } 22: } 23: }
执行命令 mvn jxr:jxr pmd:pmd
后,生成的报告(即文件 target/site/pmd.html)如图 1 所示。
Figure 1: PMD 报告实例
这个例子中,PMD 发现了两个问题。一是枚举的 static
修饰符是冗余的(枚举默认都是 static 的,可以去掉 static修饰符),二是发现了空的 catch
语句(你应该记录一些日志等)。