eclipse代码缺陷查找插件findbugs的使用

上传人:公**** 文档编号:489007345 上传时间:2022-08-13 格式:DOCX 页数:6 大小:47.17KB
返回 下载 相关 举报
eclipse代码缺陷查找插件findbugs的使用_第1页
第1页 / 共6页
eclipse代码缺陷查找插件findbugs的使用_第2页
第2页 / 共6页
eclipse代码缺陷查找插件findbugs的使用_第3页
第3页 / 共6页
eclipse代码缺陷查找插件findbugs的使用_第4页
第4页 / 共6页
eclipse代码缺陷查找插件findbugs的使用_第5页
第5页 / 共6页
点击查看更多>>
资源描述

《eclipse代码缺陷查找插件findbugs的使用》由会员分享,可在线阅读,更多相关《eclipse代码缺陷查找插件findbugs的使用(6页珍藏版)》请在金锄头文库上搜索。

1、静态分析工具承诺无需开发人员费劲就能找出代码中已有的缺陷。当然,如果有多年的编写经验,就 会知道这些承诺并不是一定能兑现。尽管如此,好的静态分析工具仍然是工具箱中的无价之宝。在这 个由两部分组成的系列文章的第一部分中,高级软件工程师Chris Grindstaff分析了 FindBugs如何 帮助提高代码质量以及排除隐含的缺陷。代码质量工具的一个问题是它们容易为开发人员提供大量但 并非真正问题的问题 即 伪问题(false positiv)&出现伪问题时,开发人员要学会忽略工具的 输出或者放弃它。FindBugs的设计者David Hovemeyer和 William Pugh注意到了这个问题

2、,并 努力减少他们所报告的伪问题数量。与其他静态分析工具不同,FindBugs不注重样式或者格式,它 试图只寻找真正的缺陷或者潜在的性能问题。FindBugs 是什么?FindBugs是一个静态分析工具,它检查类或者JAR文件,将字节码与一组缺陷模式进行对比 以发现可能的问题。有了静态分析工具,就可以在不实际运行程序的情况对软件进行分析。不是通过 分析类文件的形式或结构来确定程序的意图,而是通常使用Visitor模式(请参阅参考资料)。图1 显示了分析一个匿名项目的结果(为防止可怕的犯罪,这里不给出它的名字):在FindBugs的GUI中,需要先选择待扫描的.class文件(FindBugs其

3、实就是对编译后的class 进行扫描,藉以发现一些隐藏的bug。)。如果你拥有这些.class档对应的源文件,可把这些.java文 件再选上,这样便可以从稍后得出的报告中快捷的定位到出问题的代码上面。此外,还可以选上工程 所使用的library,这样似乎可以帮助FindBugs做一些高阶的检查,藉以发现一些更深层的bug。选定了以上各项后,便可以开始检测了。检测的过程可能会花好几分钟,具体视工程的规模而定。 检测完毕可生成一份详细的报告,藉由这份报告,可以发现许多代码中间潜在的bug。比较典型的, 如引用了空指针(null pointer dereference),特定的资源(db conne

4、ction)未关闭,等等。如果用人工检 查的方式,这些bug可能很难才会被发现,或许永远也无法发现,直到运行时发作当除掉了这些典 型的(classic) bug后,可以确信的是,我们的系统稳定度将会上一个新的台阶。以目前遇到的状况来看,FindBugs可以有两种使用时机。开发阶段当Developer完成了某一部分功能模块开发的时候(这通常是指代码撰写完成,并已debug通过 之后),可藉由FindBugs对该模块涉及的java文件进行一次扫描,以发现一些不易察觉的bug或是 效能问题。交付新版的时候,开发团队可以跑一下FindBugs,除掉一些隐藏的Bug。FindBugs得出 的报告可以作为

5、该版本的一个参考文档一并交付给测试团队留档待查。在开发阶段使用FindBugs, 方面开发人员可以对新版的品质更有信心,另一方面,测试人员 藉此可以把更多的精力放在业务逻辑的确认上面,而不是花大量精力去进一些要在特殊状况下才可能 出现的BUG(典型的如Null Pointer Dereferenee)。从而可以提高测试的效率。维护阶段这里指的是系统已经上线,却发现因为代码中的某一个bug导致系统崩溃。在除掉这个已暴露的 bug之后,为了快速的找出类似的但还未暴露的bug,可以使用FindBugs对该版的代码进行扫描。 当然,在维护阶段使用FindBugs往往是无奈之举,且时间紧迫。此外,如果本

6、来在新版交付的时候 就使用过FindBugs的话,往往意味着这种bug是FindBugs还无法检测出的。这也是FindBugs局 限的地方。FindBugs出到目前的版本,功能已经相当强大,不过也有待完善的地方。从实际使用来看,有 一些隐藏的bug并不能靠FindBugs直接发现。那么,可不可以撰写一个新的Detector,来发现这种 将一个未初始化的reference传来传去而形成的潜在的bug呢?理论上来讲,应该是可以的。这个 Detector目前还未实现。哪位如果有兴趣的话,可以参考FindBugs, Part 2: Writing custom detectors (扩展阅读)这篇文章

7、,帮忙实现这个Detector。实现一个新的Detector,便可以检测出一种新型的 bug,这样不知又可以帮开发人员省去多少人工检查的时间,功德无量啊。FindBugs也不能发现非java的Bug。对于非java撰写的代码,如javascript,SQL等等,要找 出其中可能的bug,FindBugs是无能为力的。当然,javascript中的bug似乎还不至于使系统崩溃, 而SQL中的bug往往又跟业务逻辑相关,只要测试仔细一些应该是可以发现的。FindBugs不过是一个工具。作为开发人员,当然首先要在编程的时候努力避免引入bug,而不 要依赖于某个工具来为自己把关。不过由于代码的复杂性,

8、一些隐藏的bug确实很难靠咱们的肉眼发 现。这时,应用一些好的工具或许就可以帮你发现这样的bug。这便是FingBug存在的价值。为什么应该将FindBugs集成到编译过程中?经常问到的第一个问题是为什么要将FindBugs加入到编译过程中?虽然有大量理由,最明显 的回答是要保证尽可能早地在进行编译时发现问题。当团队扩大,并且不可避免地在项目中加入更多 新开发人员时,FindBugs可以作为一个安全网,检测出已经识别的缺陷模式。我想重申在一篇 FindBugs论文中表述的一些观点。如果让一定数量的开发人员共同工作,那么在代码中就会出现缺 陷。像FindBugs这样的工具当然不会找出所有的缺陷,

9、但是它们会帮助找出其中的部分。现在找 出部分比客户在以后找到它们要好一一特别是当将FindBugs结合到编译过程中的成本是如此低 时。一旦确定了加入哪些过滤器和类,运行FindBugs就没什么成本了,而带来的好处就是它会检 测出新缺陷。如果编写特定于应用程序的检测器,则这个好处可能更大。生成有意义的结果重要的是要认识到这种成本/效益分析只有在不生成大量误检时才有效。换句话说,如果在每次 编译时,不能简单地确定是否引入了新的缺陷,那么这个工具的价值就会被抵消。分析越自动化越好。 如果修复缺陷意味着必须吃力地分析检测出的大量不相干的缺陷,那么您就不会经常使用它,或者至 少不会很好地使用它。确定不关

10、心哪些问题并从编译中排除它们。也可以挑出确实关注的一小部分检测器并只运行它 们。另一种选择是从个别的类中排除一组检测器,但是其他的类不排除。FindBugs提供了使用过滤 器的极大灵活性,这可帮助生成对团队有意义的结果,由此我们进入下一节。确定用FindBugs的结果做什么可能看来很显然,但是您想不到我参与的团队中有多少加入了类似FindBugs这样的工具而没 有真正利用它。让我们更深入地探讨这个问题用结果做什么?明确回答这个问题是困难的,因为 这与团队的组织方式、如何处理代码所有权问题等有很大关系。不过,下面是一些指导:可以考虑将FindBugs结果加入到源代码管理(SCM)系统中。一般的经

11、验做法是不将编译工 件(artifact)放到SCM系统中。不过,在这种特定情况下,打破这个规则可能是正确的,因为它 使您可以监视代码质量随时间的变化。可以选择将XML结果转换为可以发送到团队的网站上的HTML报告。转换可以用XSL样式 表或者脚本实现。有关例子请查看FindBugs网站或者邮件列表(请参阅参考资料)。像FindBugs这样的工具通常会成为用于敲打团队或者个人的政治武器。尽量抵制这种做法或 者不让它发生记住,它只是一个工具,它可以帮助改进代码的质量。有了这种思想,在下一部分 中,我将展示如何编写自定义缺陷检测器。问题发现的例子下面的列表没有包括FindBug可以找到的所有问题。

12、这里只是列举了一些比较有意思的部分。检测器:找出hash equals不匹配这个检测器寻找与equals。和hashCode()的实现相关的几个问题。这两个方法非常重要,因 为几乎所有基于集合的类一一 List、Map、Set等都调用它们。一般来说,这个检测器寻找两种不同 类型的问题当一个类:重写对象的equals()方法,但是没有重写它的hashCode方法,或者相反的情况时。定义一 个co-variant版本的equals()或compareTo()方法。例如,Bob类定义其equals()方法为布尔 equals(Bob),它覆盖了对象中定义的equals()方法。因为Java代码在编译

13、时解析重载方法的方 式,在运行时使用的几乎总是在对象中定义的这个版本的方法,而不是在Bob中定义的那一个(除 非显式将equals()方法的参数强制转换为Bob类型)。因此,当这个类的一个实例放入到类集合 中的任何一个中时,使用的是Object.equals()版本的方法,而不是在Bob中定义的版本。在这种 情况下,Bob类应当定义一个接受类型为Object的参数的equals()方法。检测器:忽略方法返 回值这个检测器查找代码中忽略了不应该忽略的方法返回值的地方。这种情况的一个常见例子是在调 用String方法时,如在清单1中:清单1.忽略返回值的例子1 String aString = b

14、ob;2 b.replace(b, p);3 if(b.equals(pop)这个错误很常见。在第2行,程序员认为他已经用p替换了字符串中的所有b。确实是这样,但是 他忘记了字符串是不可变的。所有这类方法都返回一个新字符串,而从来不会改变消息的接收者。检测器:Null指针对null的解引用(dereference)和冗余比较这个检测器查找两类问题。它查找代码路径将会或者可能造成null指针异常的情况,它还查找 对null的冗余比较的情况。例如,如果两个比较值都为null,那么它们就是冗余的并可能表明代码 错误。FindBugs在可以确定一个值为null而另一个值不为null时,检测类似的错误,

15、如清单2所 示:清单2. Null指针示例1 Person person = aMap.get(bob);2 if (person != null) 3 person.updateAccessTime();4 5 String name = person.getName(); 在这个例子中,如果第1行的Map不包括一个名为bob”的人,那么在第5行询问person的名 字时就会出现null指针异常。因为FindBugs不知道map是否包含bob”,所以它将第5行标记 为可能null指针异常。检测器:初始化之前读取字段这个检测器寻找在构造函数中初始化之前被读取的字段。这个错误通常是一一尽管不总是

16、如此 由使用字段名而不是构造函数参数引起的,如清单3所示:清单3.在构造函数中读取未初始化的字段1 public class Thing 2 private List actions;3 public Thing(String startingActions) 4 StringTokenizer tokenizer = new StringTokenizer(startingActions);5 while (tokenizer.hasMoreTokens() 6 actions.add(tokenizer.nextToken();7 8 9 在这个例子中,第6行将产生一个n ull指针异常,因为变量actio ns还没有初始化。这些例子只是FindBugs所发现的问题种类的一小部分(更多信息请参

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 机械/制造/汽车 > 电气技术

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号