use FindBugs for Java static code checking

    FindBugs-LOGO
    系统因为一个潜伏的bug发作而crash。在除掉这个已暴露的bug之后,为防止类似的但还未暴露的bug使系统再次崩溃,按普遍的做法,是由开发人员去检查每一行代码,找出其中隐藏的bug,这无疑成了每一个Develper的梦魇。而对系统来讲,以人工检查的进度,要么只能等待检查完毕后再上线,要么就无法保障上线后的稳定度。能不能有一种工具,可以帮助开发人员完成代码的检测,快速的发现其中深藏的bug呢?网上查了一下发现,有一大堆的工具可供选择: CheckStyle, PMD, JLint, FindBugs等等。此外,还学到所谓代码静态检查(Static Code Analyse)的概念,指的是不用把程序运行起来,而发现一些要在运行的时候才会出现的错误。在试过几个工具之后,发现FindBugs还算实用。以下这段引文或许可以说明它的实用性。

    代码质量工具的一个问题是它们容易为开发人员提供大量但并非真正问题的问题——即 伪问题(false positives)。出现伪问题时,开发人员要学会忽略工具的输出或者放弃它。FindBugs 的设计者 David Hovemeyer 和 William Pugh 注意到了这个问题,并努力减少他们所报告的伪问题数量。与其他静态分析工具不同,FindBugs 不注重样式或者格式,它试图只寻找真正的缺陷或者潜在的性能问题。

先从 http://findbugs.sourceforge.net/ 下载最新版的FindBugs,解压缩到FindBugs_HOME,运行FindBugs_HOME/bin/findbugs.bat,就可以把FindBugs的GUI启动起来了。FindBugs也有command line的使用模式,也可以集成到ant中,也有一些第三方提供的供集成于IDE的plug-in(如Eclipse上的plug-in),不过从易用性来讲,似乎还是用其本来提供的GUI最好。

    在FindBugs的GUI中,需要先选择待扫描的.class文件(FindBugs其实就是对编译后的class进行扫描,藉以发现一些隐藏的bug。)。如果你拥有这些.class档对应的源文件,可把这些.java文件再选上,这样便可以从稍后得出的报告中快捷的定位到出问题的代码上面。此外,还可以选上工程所使用的library,这样似乎可以帮助FindBugs做一些高阶的检查,藉以发现一些更深层的bug。
    选定了以上各项后,便可以开始检测了。检测的过程可能会花好几分钟,具体视工程的规模而定。检测完毕可生成一份详细的报告,藉由这份报告,可以发现许多代码中间潜在的bug。比较典型的,如引用了空指针(null pointer dereference), 特定的资源(db connection)未关闭,等等。如果用人工检查的方式,这些bug可能很难才会被发现,或许永远也无法发现,直到运行时发作…当除掉了这些典型的(classic) bug后,可以确信的是,我们的系统稳定度将会上一个新的台阶。

    以目前遇到的状况来看,FindBugs可以有两种使用时机。
  • 开发阶段
    当Developer完成了某一部分功能模块开发的时候(这通常是指代码撰写完成,并已debug通过之后),可藉由FindBugs对该模块涉及的java文件进行一次扫描,以发现一些不易察觉的bug或是效能问题。交付新版的时候,开发团队可以跑一下FindBugs,除掉一些隐藏的Bug。FindBugs得出的报告可以作为该版本的一个参考文档一并交付给测试团队留档待查。
    在开发阶段使用FindBugs,一方面开发人员可以对新版的品质更有信心,另一方面,测试人员藉此可以把更多的精力放在业务逻辑的确认上面,而不是花大量精力去进一些要在特殊状况下才可能出现的BUG(典型的如Null  Pointer Dereference)。从而可以提高测试的效率。

  • 维护阶段
    这里指的是系统已经上线,却发现因为代码中的某一个bug导致系统崩溃。在除掉这个已暴露的bug之后,为了快速的找出类似的但还未暴露的 bug,可以使用FindBugs对该版的代码进行扫描。当然,在维护阶段使用FindBugs往往是无奈之举,且时间紧迫。此外,如果本来在新版交付的时候就使用过FindBugs的话,往往意味着这种bug是FindBugs还无法检测出的。这也是FindBugs局限的地方。

    FindBugs出到目前的版本,功能已经相当强大,不过也有待完善的地方。从实际使用来看,有一些隐藏的bug并不能靠FindBugs直接发现。例如,最新版的FindBugs可发现null pointer dereference的写法,如
StringBuffer sb  =   null ;
sb.append(“”);

这种写法显然会导致运行时出现NullPointerException。但如果代码改为
StringBuffer sb  =   null ;
useAStringBuffer(sb);
void  useAStringBuffer(StringBuffer sb) {
    sb.append();
}

    这样的写法,运行时虽然也会报NullPointerException,但FindBugs无法检测出这种错误。这样的bug对 FindBugs来讲便是一个新型的Bug。FindBugs支援Developer开发自己的bug检测器(Detector)来发现现有版本的FindBugs所不能发现的bug。那么,可不可以撰写一个新的 Detector,来发现这种将一个未初始化的reference传来传去而形成的潜在的bug呢?理论上来讲,应该是可以的。这个 Detector目前还未实现。哪位如果有兴趣的话,可以参考 FindBugs, Part 2: Writing custom detectors这篇文章,帮忙实现这个Detector。实现一个新的Detector,便可以检测出一种新型的bug,这样不知又可以帮开发人员省去多少人工检查的时间,功德无量啊。

    FindBugs也不能发现非java的Bug。对于非java撰写的代码,如javascript,SQL等等,要找出其中可能的bug,FindBugs是无能为力的。当然,javascript中的bug似乎还不至于使系统崩溃,而SQL中的bug往往又跟业务逻辑相关,只要测试仔细一些应该是可以发现的。

    FindBugs不过是一个工具。作为开发人员,当然首先要在编程的时候努力避免引入bug,而不要依赖于某个工具来为自己把关。不过由于代码的复杂性,一些隐藏的bug确实很难靠咱们的肉眼发现。这时,应用一些好的工具或许就可以帮你发现这样的bug。这便是FingBug存在的价值。


参考资源
FindBugs, Part 1: Improve the quality of your code
(中文版)http://www-900.ibm.com/developerWorks/cn/java/j-findbug1/index.shtml
(英文原版)http://www-106.ibm.com/developerworks/java/library/j-findbug1/

FindBugs, Part 2: Writing custom detectors
http://www-128.ibm.com/developerworks/java/library/j-findbug2/





 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值