首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

用 PMD 铲除 bug(1)

用 PMD 铲除 bug(1)

Tom Copeland 的 PMD 是一个开源(BSD 许可)工具,它分析 Java 源代码,找出潜在的 bug。在一般意义上来说,它与 FindBugs 和 Lint4j 这类工具类似(请参阅 )。但是,所有这些工具找出的 bug 各不相同,所以在给定代码基址上把这些工具都运行一遍很有好处。在本文中,我将解释如何使用 PMD,并展示可以从 PMD 中获得什么。本文将介绍 PMD 的命令行界面。您也可以把 PMD 与 Ant 集成在一起,以便进行自动源代码检查,而且还可以将 PMD 与一些可用于大多数主要 IDE 和程序员编辑器的插件集成在一起。      
安装并运行 PMDPMD 是用 Java 编程语言编写的,并且要求使用 JDK 1.3 或更高的版本。如果您习惯使用命令行,那么 PMD 的安装和运行会非常简单。先下载 zip 压缩文件(请参阅 ),然后把它解压到合适的位置,比如 /usr 或您自己的主目录中。本文假设您把它解压到 /usr 中。      
运行 PMD 最简单的方法是调用脚本 pmd.sh(在 Unix/Linux 上)或脚本 pmd.bat(在 Windows 上)。不太合常规的是,这些脚本在 pmd-2.1/etc 目录中,而不是在 bin 目录中。这个脚本采用了三个命令行参数:
  • 要检查的 .java 文件的路径。
  • 指定输出格式的关键字           html 或           xml。
  • 要运行的规则集的名称。
例如,以下命令使用命名规则集检查 ImageGrabber.java 文件并生成 XML 输出:
1
$ /usr/pmd-2.1/etc/pmd.sh ImageGrabber.java xml rulesets/naming.xml




分析结果以上命令的输出类似于清单 1 中的报告,如下所示,默认情况下,这些输出被发送到         System.out:      
清单 1. PMD 的 XML 报告
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0"?><pmd>
<file name="/Users/elharo/src/ImageGrabber.java">
<violation line="32" rule="ShortVariable"
           ruleset="Naming Rules" priority="3">
Avoid variables with short names like j
</violation>
<violation line="105" rule="VariableNamingConventionsRule"
           ruleset="Naming Rules" priority="1">
Variables that are not final should not contain underscores
(except for underscores in standard prefix/suffix).
</violation>
</file>
<error filename="/Users/elharo/src/ImageGrabber.java"
  msg="Error while processing /Users/elharo/ImageGrabber.java"/>
</pmd>




在清单 1 中可以看到,PMD 发现了两个问题:在 ImageGrabber.java 的第 32 行有一个短变量名称,在第 105 行的名称中有一个下划线。这些看起来可能是小问题,但是后果却可能是惊人的。在这个例子中,105 行的下划线只是一个有 10 年之久的老代码中一些容易修正的小毛病。但是仔细考察第一个问题,使我认识到可以完全排除         j 变量,因为它与另外一个单独递增变量的功能相同。这个程序仍然有用,但是它应该更简洁一些,以便应对以后的挑战。每当清除一行代码,也就减少了一个可能隐匿 bug 的地方。      
您可以把 PMD 的输出重定向到文件中,或者通过管道,以常见的方式将它传递到编辑器中。我通常更喜欢生成 HTML 格式的输出,并将它加载到 Web 浏览器中,如图 1 中所示:
图 1. PMD 用 HTML 格式处理后的输出在检查源代码树时,把结果输出到文件中会非常有帮助。如果把目录、zip 文件或 JAR 档案文件传递给第一个参数,那么 PMD 会递归地检查目录或档案中的每个 .java 文件。输出的总量可能有些吓人,特别是在 PMD 生成大量误报(false positive)的时候。例如,当针对 XOM(请参阅 )代码基址运行 PMD 时,它不断地报告应当“Avoid variables with short names like in.”(避免像 in 这样的短变量名)。而我却恰恰认为“in”是指向         InputStream 的变量的非常好的名称。尽管如此,如果用一个好的文档编辑器来查看输出,您通常会发现,可以很容易地认出并删除最常见的误报,因为它们通常非常相似;然后您就可以解决其余的问题了。      
PMD 中惟一缺乏的特性就是不能向源代码中添加 “lint 注释”,以便对要执行的一些明显有危险的操作进行提醒。不过,也许这是一项特性,而不是 bug。只有一次,我改变了自己对真正误报的看法,觉得 PMD 始终是正确的。例如,对于一个长时间的         try-        catch 块,类似 XOM 中的不同地方出现的那个 try-catch 块:      
1
2
3
4
5
6
try {
  this.data = data.getBytes("UTF8");
}
catch (UnsupportedEncodingException ex) {
  // All VMs support UTF-8
}




PMD 把这标记为空         catch 块。这看起来不是什么问题,但是后来我发现某些虚拟机实际上不认识 UTF-8 编码,尽管这会使它们不符合标准。所以我把这个块修改如下,然后 PMD 开始停止报错:      
1
2
3
4
5
6
try {
  this.data = data.getBytes("UTF8");
}
catch (UnsupportedEncodingException ex) {
   throw new RuntimeException("Broken VM: Does not support UTF-8");
}

返回列表