Java代码缺陷自动分析工具介绍

java代码缺陷自动分析工具介绍

黄锡波

java代码缺陷自动分析工具主要有:findbugs、pmd和checkstyle工具。这里重点介绍findbugs的使用,简要提及pmd和checkstyle工具的使用。

1findbugs是什么?

findbugs 是一个java bytecode静态分析工具,它可以帮助java工程师提高代码质量以及排除隐含的缺陷。

findbugs检查类或者 jar 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。

有了静态分析工具,就可以在不实际运行程序的情况对软件进行分析。findbugs不是通过分析类文件的形式或结构来确定程序的意图,而是通常使用 visitor 模式进行分析(visitor 模式的更多信息)。

2findbugs可以做什么?

findbugs提供了35个检测器来检测字节码中可能的缺陷。可以做的事情主要有:

2.1找出 hash equals 不匹配

找与 equals() 和 hashcode() 的实现相关的几个问题。这两个方法非常重要,因为几乎所有基于集合的类---list、map、set 等都调用它们。一般来说,这个检测器寻找两种不同类型的问题:

①当一个类重写对象的 equals() 方法,但是没有重写它的 hashcode 方法,或者相反的情况时。

②定义一个 co-variant 版本的 equals() 或 compareto() 方法。例如, bob 类定义其 equals() 方法为布尔 equals(bob) ,它覆盖了对象中定义的 equals() 方法。因为 java 代码在编译时解析重载方法的方式,在运行时使用的几乎总是在对象中定义的这个版本的方法,而不是在 bob 中定义的那一个(除非显式将 equals() 方法的参数强制转换为 bob 类型)。因此,当这个类的一个实例放入到类集合中的任何一个中时,使用的是 object.equals() 版本的方法,而不是在 bob 中定义的版本。在这种情况下, bob 类应当定义一个接受类型为 object 的参数的 equals() 方法。

2.2检测:忽略方法返回值

这个检测器查找代码中忽略了不应该忽略的方法返回值的地方。这种情况的一个常见例子是在调用 string 方法时,例如:

1 string astring = "bob";

2 b.replace('b', 'p');

3 if(b.equals("pop"))

这个错误很常见。在第 2 行,程序员认为他已经用 p 替换了字符串中的所有 b。确实是这样,但是他忘记了字符串是不可变的。所有这类方法都返回一个新字符串,而从来不会改变消息的接收者。

2.3检测:null 指针对 null 的解引用(dereference)和冗余比较

这个检测器查找两类问题。它查找代码路径将会或者可能造成 null 指针异常的情况,它还查找对 null 的冗余比较的情况。例如,如果两个比较值都为 null,那么它们就是冗余的并可能表明代码错误。findbugs 在可以确定一个值为 null 而另一个值不为 null 时,检测类似的错误,例如:

1 person person = amap.get("bob");

2 if (person != null) {

3person.updateaccesstime();

4 }

5 string name = person.getname();

在这个例子中,如果第 1 行的 map 不包括一个名为“bob”的人,那么在第 5 行询问 person 的名字时就会出现 null 指针异常。因为 findbugs 不知道 map 是否包含“bob”,所以它将第 5 行标记为可能 null 指针异常。

2.4检测:初始化之前读取字段

这个检测器寻找在构造函数中初始化之前被读取的字段。这个错误通常是由使用字段名而不是构造函数参数引起的,例如在构造函数中读取未初始化的字段:

1 public class thing {

2private list actions;

3public thing(string startingactions) {

4stringtokenizer tokenizer = new stringtokenizer(startingactions);

5while (tokenizer.hasmoretokens()) {

6actions.add(tokenizer.nexttoken());

7}

8}

9 }

在这个例子中,第 6 行将产生一个 null 指针异常,因为变量 actions 还没有初始化。

2.5命名检查

对标准 java 命令规范的测试:变量名称不应太短;方法名称不应过长;类名称应当以小写字母开头;方法和字段名应当以小写字母开头,等等。

2.6未使用的代码检查

查找从未使用的私有字段和本地变量、执行不到的语句、从未调用的私有方法,等等。

2.7嵌套检查

例如: switch 语句应当有 default 块,应当避免深度嵌套的 if 块,不应当给参数重新赋值,不应该对 double 值进行相等比较。

2.8导入语句检查

检查 import 语句的问题,比如同一个类被导入两次或者被导入 java.lang 的类中。

2.9junit 测试检查

查找测试用例和测试方法的特定问题,例如方法名称的正确拼写,以及 suite() 方法是不是 static 和 public。

2.10字符串检查

找出处理字符串时遇到的常见问题,例如重复的字符串标量,调用 string 构造函数,对 string 变量调用 tostring() 方法。

2.11括号检查

检查 for、 if、 while 和 else 语句是否使用了括号。

2.12代码尺寸检查

测试过长的方法、有太多方法的类以及重构方面的类似问题。

2.13终结函数检查

因为在 java 语言中, finalize() 方法不是那么普遍,它们的使用规则虽然很详细,但是人们对它们相对不是很熟悉。这类检查查找 finalize() 方法的各种问题,例如空的终结函数,调用其他方法的 finalize() 方法,对 finalize() 的显式调用,等等。

2.14克隆检查

用于 clone() 方法的新规则。凡是重写 clone() 方法的类都必须实现 cloneable, clone() 方法应该调用 super.clone(),而 clone() 方法应该声明抛出 clonenotsupportedexception 异常,即使实际上没有抛出异常,也要如此。

2.15耦合检查

查找类之间过度耦合的迹象,比如导入内容太多;在超类型或接口就已经够用的时候使用子类的类型;类中的字段、变量和返回类型过多等。

2.16异常检查

针对异常的检查:不应该声明该方法而抛出 java.lang.exception 异常,不应当将异常用于流控制,不应该捕获 throwable,等等。

2.17日志检查

查找 java.util.logging.logger 的不当使用,包括非终状态(nonfinal)、非静态的记录器,以及在一个类中有多个记录器。

2.18open—close检查

检查文件或通讯方面,是否忘记close的情况。

2.19其它检查

其它缺陷清单可参见:缺陷清单

2.20构建自己的规则集

可以构建自己的规则集

3准备使用findbugs

findbugs目前最新版本是 0.9.3 。文件名是:findbugs-0.9.3.zip(windows)或findbugs-0.9.3.tar.gz(unix)。(下载网页)

也可以到starteam取相应安装文件到本地,将它解压缩到所选的目录中,安装就完成了。

要运行 findbugs,需要一个版本 1.4 或者更高的 java development kit (jdk)。

安装完后,要增加两个环境变量:

findbugs_home,例如:findbugs_home =d:\findbugs-0.9.3

java_home,例如:java_home=d:\j2sdk1.4.2_06

在 findbugs 主目录中,有几个值得注意的目录。文档在 doc 目录中,但是对我们来说更重要的是bin 目录,该包含了运行 findbugs 的批处理文件。

4运行 findbugs

像如今的大多数数工具一样,可以以多种方式运行 findbugs——从 gui、从命令行、使用 ant、作为 eclipse 插件程序和使用 maven。

这里将重点提及从 gui 运行 findbugs,简要提及使用ant 和命令行运行。

4.1findbugs ui

使用 findbugs ui 很直观。使用 findbugs ui 的一个好处是对每一个检测到的问题提供了说明,图 1 显示了缺陷 test的说明。

图一:项目test的缺陷说明

 

对每一种缺陷模式提供了类似的说明。窗口下面的 source code 选项卡很有用。如果告诉 findbugs 在什么地方寻找代码,它就会在转换到相应的选项卡时突出显示有问题的那一行。

图一中的上部有根据不同类别来检查缺陷的选项,选项有(by class、by package、by bug type、by bug category)。

图二是【file】选项,主要功能有:创建新项目、打开/关闭项目、储存项目、储存bugs信息、装载buugs信息

 

图三是【view】选项,这些选项很有用,可以切换不同模式的视图。

 

图四是【settings】选项,是对检测的缺陷模式进行选择。

 

图五是【创建新项目】选项

 

4.2使用 findbugs ui步骤

第一次使用

(1)依照图五【创建新项目】选项说明,先创建新项目,输入被检查的class或jar路径、java源文件路径及程序运行依赖的class或jar路径

(2)按【fingbugs】按钮开始检查

(3)如果出现下图六的警告

 

说明程序运行依赖的class或jar路径不对或依赖文件不完整,应依据警告信息完善。

(4)按【ok】后即进入上图一的错误信息显示

(5)选择【file】储存新建的项目

(6)选择【file】储存新扫描的bugs信息(xml文件)

非第一次使用

(1)选择【file】装载上次新建的项目并运行

(2)也可以选择【file】装载上次储存的bugs信息来查看

值得一提的还有在将 finbugs 作为 ant 任务或者在命令行中运行 findbugs 时,选择 xml 作为 ouput 选项,可以将上一次运行的结果装载到 ui 中。这样做是同时利用基于命令行的工具和 ui 工具的优点的一个很好的方法。

4.3findbugs 作为 ant 任务

如何在 ant 编译脚本中使用 findbugs?首先将 findbugs ant 任务拷贝到 ant 的 lib 目录中,这样 ant 就知道新的任务。将 find_bugs_home\lib\findbugs-ant.jar 拷贝到 ant_home\lib。

现在看看在编译脚本中要加入什么才能使用 findbugs 任务。因为 findbugs 是一个自定义任务,将需要使用 taskdef 任务以使 ant 知道装载哪一个类。通过在编译文件中加入以下一行:

在定义了 taskdef 后,可以用它的名字 findbugs 引用它。下一步要在编译中加入使用新任务的目标,示例如下:

1

2

home="${findbugs.home}" output="xml" outputfile="jedit-output.xml">

3

4下载网页)。

pmd的运行环境是j2se1.3或以后版本,安装过程同样也是解压即可。

5.1.1 ant task的使用

(1)把lib中所有的jar复制到项目的classpath中。

(2)将pmd-2.0.jar中的rulesets解压到指定目录,这里面定义了分析所需要的规则集合。

(3)修改build.xml文件。在这一版本中,提供了2个ant task。一个是pmd使用规则集合进行分析;另一个是检查代码中copy & paste代码。这2个任务对应的ant task使用:

pmd任务:

定义任务和任务所属类所在的classpath引用 -->

classpathref="classpath"/>

检查使用的规则文件 -->

输出格式和文件名 -->

所需要依赖包的classpath引用 -->

要检查的项目源文件根目录 -->

cpd任务:

定义任务和任务所属类所在的classpath -->

classpathref="classpath"/>

指明输出文件和判断属于copy & paste的标准 -->

要检查的项目源文件根目录 -->

(4)运行ant pmd和ant cpd即可。

(5)参数说明:

-formatter,指明输出格式和文件。

-rulesetfiles,指明分析所需的规则文件,不同文件使用逗号分隔。

-failonerror,pmd执行出错是否中止构建过程。

-failonruleviolation,如果与规则冲突,是否中止构建过程。

-classpath,pmd所需的classpath。

-printtoconsole,在发现问题时是否打印到ant log或控制台。

-shortfilenames,在输出报告中是否使用短文件名。

-targetjdk13,是否把目标定为jdk13,如不能使用assert。

-failurespropertyname,在任务结束时,插入违反规则的号码

-encoding,读源文件时所采用的编码,如utf-8。

5.1.2 text的使用

把bin目录下的pmd.bat修改为:

java -jar ..\lib\pmd-3.3.jar d:\temp\hpmts_2.jar[huangxb1]text[huangxb2]rulesets/basic.xml[huangxb3] ,rulesets/braces.xml,rulesets/clone.xml,rulesets/codesize.xml,rulesets/controversial.xml,rulesets/coupling.xml, rulesets/design.xml,rulesets/favorites.xml,rulesets/finalizers.xml,rulesets/unusedcode.xml,rulesets/sunsecure.xml,rulesets/strings.xml,rulesets/strictexception.xml,rulesets/scratchpad.xml,rulesets/optimizations.xml,rulesets/naming.xml,rulesets/my-rules.xml,rulesets/logging-java.xml,rulesets/logging-jakarta-commons.xml,rulesets/junit.xml,rulesets/javabeans.xml,rulesets/imports.xml

5.1checkstyle工具

checkstyle目前最新版本是: checkstyle-4.0-beta6(下载网页)。

checkstyle的运行环境是j2se1.3或以后版本,安装过程同样也是解压即可。

5.2.1ant task的使用

(1)复制checkstyle-4.0-beta6.jar到项目的classpath中。

(2)修改build.xml文件:

classpath="${weblib.dir}/checkstyle-all-3.3.jar"/>

指明checkstyle的分析所需的规则文件 -->

要检查的文件 -->

指明输出格式和文件名 -->

将xml文件转换成html文件 -->

(3)运行ant checkstyle即可。

checkstyle的规则文件,即项目的代码规范,建议不要手工书写。可以使用checkstyle plug in在eclipse配置后再导出。checkstyle提供了缺省的xslt,用来进行xml的格式转换。它们都放在contrib目录中。checkstyle同样也提供了自定义的check,但与pmd相比,书写要复杂。

6志鸿公司使用自动分析工具案例

志鸿公司目前在hpc项目中使用java代码缺陷自动分析工具。

该项目以使用fingbugs ui工具为主,pmd为辅助工具。自动分析输出的结果经过验证确认后,作为缺陷管理的组成部分之一。

经过一个多月来的运作,证实自动分析工具对改进代码的质量起到很大的作用。

[huangxb1]被检测的java源文件

[huangxb2]text模式

[huangxb3]检测器名字,所有检测器在pmd-3.3.jar里面的rulesets目录


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值