2022年FindBugs测试程序 .pdf
《2022年FindBugs测试程序 .pdf》由会员分享,可在线阅读,更多相关《2022年FindBugs测试程序 .pdf(21页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、FindBugs第 1 部分: 提高代码质量静态分析工具承诺无需开发 人员费劲就能找出代码中已有的缺陷 。当然,如果有多年的编写经验, 就会知道这些承诺并不是一定能兑现。尽管如此, 好的静态分析工具仍然是工具箱中的无价之宝。在这个由两部分组成的系列文章的第一部分中,高级软件工程 师 Chris Grindstaff 分析了FindBugs 如何帮助提高代码质量以及排除隐含的缺陷。代码质量工具的一个问题是它们容易为开发 人员提供大量但并非真正问题的问题 即伪问题 (false positives)。 出现伪问题时, 开发人员要学会忽略工具的输出或者放弃它。FindBugs 的设计者David H
2、ovemeyer 和 William Pugh 注意到了这个问题, 并努力减少他们所报告的伪问题数量。与其他静态分析工具不同,FindBugs 不注重样式或者格式,它试图只寻找真正的缺陷或者潜在的性能 问题。FindBugs 是什么?FindBugs 是一个静态分析工具,它检查类或者JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。有了静态分析工具,就可以在不实际运行程序的情况对软件进行分析。不是通过分析类文件的形式或结构来确定程序的意图,而是通常使用Visitor 模式(请参阅参考 资料 )。图 1 显示了分析一个匿名项目的结果(为防止可怕的犯罪,这里不给出它的名字):名师资料总
3、结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 21 页 - - - - - - - - - 图 1. FindBugs UI让我们看几个FindBugs 可以发现的问题。问题发现的例子本系列的第二篇文章“ 编写自定义检测器” 解释了如何编写自定义检测器,以便发现特定于应用程序的问题。回页首名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 21 页 - - -
4、- - - - - - 下面的列表没有包括FindBug 可以找到的所有问题。相反,我侧重于一些更有意思的问题。检测器:找出hash equals 不匹配这个检测器寻找与equals()和hashCode()的实现相关的几个问题。这两个方法非常重要,因为几乎所有基于集合的类 List、Map、Set 等都调用它们。一般来说,这个检测器寻找两种不同类型的问题 当一个类:重写对象的equals()方法,但是没有重写它的hashCode方法,或者相反的情况时。定义一个co-variant 版本的equals()或compareTo()方法。例如,Bob类定义其equals()方法为布尔equals(
5、Bob),它覆盖了对象中定义的equals()方法。因为Java 代码在编译时解析重载方法的方式, 在运行时使用的几乎总是在对象中定义的这个版本的方法,而不是在Bob中定义的那一个(除非显式将equals()方法的参数强制转换为Bob类型)。因此,当这个类的一个实例放入到类集合中的任何一个中时,使用的是Object.equals()版本的方法,而不是在Bob中定义的版本。在这种情况下,Bob类应当定义一个接受类型为Object的参数的equals()方法。检测器:忽略方法返回值这个检测器查找代码中忽略了不应该忽略的方法返回值的地方。这种情况的一个常见例子是在调用String方法时,如在清单1
6、中:清单1. 忽略返回值的例子1 String aString = bob; 2 b.replace(b, p); 3 if(b.equals(pop) 这个错误很常见。 在第2 行,程序员 认为他已经用p 替换了字符串中的所有b。确实是这样,但是他忘记了字符串是不可变的。所有这类方法都返回一个新字符串,而从来不会改变消息的接收者。检测器: Null 指针对null 的解引用( dereference)和冗余比较这个检测器查找两类问题。它查找代码路径将会或者可能造成null 指针异常的情况,它还查找对null 的冗余比较的情况。例如,如果两个比较值都为null ,那么它们就是冗余的并可能表明代
7、码错误。FindBugs 在可以确定一个值为null 而另一个值不为null 时,检测类似的错误,如清单2 所示:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 21 页 - - - - - - - - - 清单2. Null 指针示例1 Person person = aMap.get(bob); 2 if (person != null) 3 person.updateAclearcase/ target=_blank ccessTime(); 4 5 String
8、name = person.getName(); 在这个例子中,如果第1 行的Map不包括一个名为“bob”的人,那么在第5 行询问person的名字时就会出现null 指针异常。因为FindBugs 不知道map 是否包含 “bob”,所以它将第 5 行标记为可能null 指针异常。检测器:初始化之前读取字段这个检测器寻找在构造函数中初始化之前被读取的字段。这个错误通常是尽管不总是如此 由使用字段名而不是构造函数参数引起的,如清单3 所示:清单3. 在构造函数中读取未初始化的字段1 public class Thing 2 private List actions; 3 public Thi
9、ng(String startingActions) 4 StringTokenizer tokenizer = new StringTokenizer(startingActions); 5 while (tokenizer.hasMoreTokens() 6 actions.add(tokenizer.nextToken(); 7 8 9 在这个例子中,第6 行将产生一个null 指针异常,因为变量actions还没有初始化。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页
10、,共 21 页 - - - - - - - - - 这些例子只是FindBugs 所发现的问题种类的一小部分(更多信息请参阅参考资料 )。在撰写本文时, FindBugs 提供总共35 个检测器。开始使用FindBugs 要运行FindBugs,需要一个版本1.4 或者更高的Java Development Kit (JDK),尽管它可以分析由老的JDK 创建的类文件。要做的第一件事是下载 并安装最新发布的FindBugs 当前是0.7.1 (请参阅参考资料 )。幸运的是,下载 和安全 是相当简单的。在下载了zip 或者tar 文件后,将它解压缩到所选的目录中。就是这样了 安装就完成了。安装完
11、后,对一个示例类运行它。就像一般文章中的情况,我将针对Windows用户进行讲解,并假定那些Unix 信仰者可以熟练地转化这些内容并跟进。打开命令行提示符号并进入FindBugs 的安装目录。对我来说,这是C:appsFindBugs-0.7.3 。在 FindBugs 主目录中,有几个值得注意的目录。文档在doc 目录中,但是对我们来说更重要的是, bin 目录包含了运行FindBugs 的批处理文件,这使我们进入下一部分。运行FindBugs 像如今的大多数数工具一样,可以以多种方式运行FindBugs 从 GUI 、从命令行、使用Ant、作为Eclipse 插件程序和使用Maven。我将
12、简要提及从GUI 运行FindBugs,但是重点放在用Ant 和命令行运行它。 部分原因是由于GUI 没有提供命令行的所有选项。例如,当前不能指定要加入的过滤器或者在UI 中排除特定的类。但是更重要的原因是我认为FindBugs 最好作为编译的集成部分使用,而UI 不属于自动编译。回页首回页首名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 21 页 - - - - - - - - - 使用 FindBugs UI使用FindBugs UI 很直观,但是有几点值得说明。如图
13、 1 所示,使用FindBugs UI 的一个好处是对每一个检测到的问题提供了说明。图1 显示了缺陷Naked notify in method 的说明。 对每一种缺陷模式提供了类似的说明,在第一次熟悉这种工具时这是很有用的。窗口下面的Source code 选项卡也同样有用。如果告诉FindBugs 在什么地方寻找代码,它就会在转换到相应的选项卡时突出显示有问题的那一行。值得一提的还有在将FinBugs 作为Ant 任务或者在命令行中运行FindBugs 时,选择xml作为ouput选项,可以将上一次运行的结果装载到UI 中。这样做是同时利用基于命令行的工具和UI 工具的优点的一个很好的方法
14、。将 FindBugs 作为 Ant 任务运行让我们看一下如何在Ant 编译脚本中使用FindBugs。首先将FindBugs Ant 任务拷贝到Ant 的 lib 目录中,这样 Ant 就知道新的任务。 将 FIND_ BUGS_HOMElibFindBugs-ant.jar 拷贝到ANT _HOMElib 。现在看看在编译脚本中要加入什么才能使用FindBugs 任务。因为FindBugs 是一个自定义任务, 将需要使用taskdef任务以使Ant 知道装载哪一个类。通过在编译文件中加入以下一行做到这一点: 在定义了taskdef后,可以用它的名字FindBugs引用它。 下一步要在编译中
15、加入使用新任务的目标,如清单4 所示:清单4. 创建 FindBugs 目录1 2 3 4 5 6 7 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 21 页 - - - - - - - - - 让我们更详细地分析这段代码中所发生的过程。第 1 行:注意target取决于编译。一定要记住处理的是类文件而不是源文件,这样使target对应于编译目标保证了FindBugs 可在最新的类文件运行。FindBugs 可以灵活地接受多种输入,包括一组类文件、JAR 文件、或者一组
16、目录。第 2 行: 必须指定包含FindBugs 的目录,我是用Ant 的一个属性完成的,像这样: 可选属性output指定 FindBugs 的结果使用的输出格式。可能的值有xml、text或者emacs。如果没有指定outputFile,那么FindBugs 会使用标准输出。如前所述,XML 格式有可以在UI 中观看的额外好处。第 3 行:class元素用于指定要FindBugs 分析哪些JAR、类文件或者目录。 分析多个JAR 或者类文件时,要为每一个文件指定一个单独的class元素。除非加入了projectFile元素,否则需要class元素。更多细节请参阅FindBugs 手册。第
17、4 行:用嵌套元素auxClasspath列出应用程序的依赖性。这些是应用程序需要但是不希望 FindBugs 分析的类。 如果没有列出应用程序的依赖关系,那么FindBugs 仍然会尽可能地分析类, 但是在找不到一个缺少的类时,它会抱怨。 与class元素一样, 可以在FindBugs 元素中指定多个auxClasspath元素。auxClasspath元素是可选的。第 5 行:如果指定了sourcePath元素,那么path属性应当表明一个包含应用程序源代码的目录。指定目录使FindBugs 可以在GUI 中查看XML 结果时突出显示出错的源代码。这个元素是可选的。上面就是基本内容了。让我
18、们提前几个星期。过滤器您已经将FindBugs 引入到了团队中,并运行它作为您的每小时/每晚编译过程的一部分。当团队越来越熟悉这个工具时,出于某些原因, 您决定所检测到的一些缺陷对于团队来说不重要。也许您不关心一些类是否返回可能被恶意修改的对象 也许,像JEdit,有一个真正需要的( honest-to-goodness)、合法的理由调用System.gc()。总是可以选择 “ 关闭 ” 特定的检测器。 在更细化的水平上,可以在指定的一组类甚至是方法中查找问题时,排除某些检测器。FindBugs 提供了这种细化的控制,可以排除或者包含过滤器。当前只有用命令行或者Ant 启动的FindBugs
19、中支持排除和包含过滤器。正如其名字所表明的, 使用排除过滤器来排除对某些缺陷的报告。较为少见但仍然有用的是,包含过滤器只能用于报告指定的缺陷。过滤器是在一个XML 文件中定义的。可以在命令行中用一个排除或者包含开关、或者在Ant 编译文件中用excludeFilter和includeFilter指定它们。在下面的例子中,假定使用排除开关。还要注意在下面的讨论中,我对“ bugcode” 、“ bug” 和“ detector”的使用具有某种程度的互换性。可以有不同的方式定义过滤器:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - -
20、名师精心整理 - - - - - - - 第 7 页,共 21 页 - - - - - - - - - 匹配一个类的过滤器。可以用这些过滤器忽略在特定类中发现的所有问题。匹配一个类中特定缺陷代码(bugcode)的 过滤器。 可以用这些过滤器忽略在特定类中发现的一些缺陷。匹配一组缺陷的过滤器。可以用这些过滤器忽略所分析的所有类中的一组缺陷。匹配所分析的一个类中的某些方法的过滤器。可以用这些过滤器忽略在一个类中的一组方法中发现的所有缺陷。匹配在所分析的一个类中的方法中发现的某些缺陷的过滤器。可以用这些过滤器忽略在一组方法中发现的特定缺陷。知道了这些就可以开始使用了。有关其他定制FindBugs
21、方法的更多信息, 请参阅FindBugs 文档。 知道如何设置编译文件以后,就让我们更详细地分析如何将FindBugs 集成到编译过程中吧!将 FindBugs 集成到编译过程中在将FindBugs 集成到编译过程当中可以有几种选择。总是可以在命令行执行FindBugs,但是您很可能已经使用Ant 进行编译,所以最自然的方法是使用FindBugs Ant 任务。因为我们在如何运行FindBugs 一节中讨论了使用FindBugs Ant 任务的基本内容,所以现在讨论应当将FindBugs 加入到编译过程中的几个理由,并讨论几个可能遇到的问题。为什么应该将FindBugs 集成到编译过程中?经常
22、问到的第一个问题是为什么要将FindBugs 加入到编译过程中?虽然有大量理由,最明显的回答是要保证尽可能早地在进行编译时发现问题。当团队扩大, 并且不可避免地在项目中加入更多新开发人员时,FindBugs 可以作为一个 安全 网,检测出已经识别的缺陷模式。我想重申在一篇FindBugs 论文中表述的一些观点。如果让一定数量的开发人员共同工作,那么在代码中就会出现缺陷。像 FindBugs 这样的工具当然不会找出所有的缺陷,但是它们会帮助找出其中的部分。现在找出部分比客户在以后找到它们要好特别是当将FindBugs 结合到编译过程中的成本是如此低时。一旦确定了加入哪些过滤器和类,运行FindB
23、ugs 就没什么成本了,而带来的好处就是它会检测出新缺陷。如果编写特定于应用程序的检测器,则这个好处可能更大。生成有意义的结果回页首名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 21 页 - - - - - - - - - 重要的是要认识到这种成本/效益分析只有在不生成大量误检时才有效。换句话说,如果在每次编译时, 不能简单地确定是否引入了新的缺陷,那么这个工具的价值就会被抵消。分析越自动化 越好。如果修复缺陷意味着必须吃力地分析检测出的大量不相干的缺陷,那么您就不会经
24、常使用它,或者至少不会很好地使用它。确定不关心哪些问题并从编译中排除它们。也可以挑出确实关注的一小部分检测器并只运行它们。另一种选择是从个别的类中排除一组检测器,但是其他的类不排除。FindBugs 提供了使用过滤器的极大灵活性,这可帮助生成对团队有意义的结果,由此我们进入下一节。确定用 FindBugs 的结果做什么可能看来很显然, 但是您想不到我参与的团队中有多少加入了类似FindBugs 这样的工具而没有真正利用它。 让我们更深入地探讨这个问题 用结果做什么?明确回答这个问题是困难的, 因为这与团队的组织方式、如何处理代码所有权问题等有很大关系。不过, 下面是一些指导:可以考虑将Find
25、Bugs 结果加入到源代码管理(SCM )系统中。 一般的经验做法是不将编译工件(artifact)放到 SCM 系统中。 不过,在这种特定情况下,打破这个规则可能是正确的,因为它使您可以监视代码质量随时间的变化。可以选择将XML 结果转换为可以发送到团队的网站上的HTML 报告。转换可以用XSL 样式表或者脚本实现。有关例子请查看FindBugs 网站或者邮件列表 (请参阅参考资料 )。像 FindBugs 这样的工具通常会成为用于敲打团队或者个人的政治武器。尽量抵制这种做法或者不让它发生 记住,它只是一个工具,它可以帮助改进代码的质量。有了这种思想,在下一部分中,我将展示如何编写自定义缺陷
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年FindBugs测试程序 2022 FindBugs 测试 程序
限制150内