教程集 www.jiaochengji.com
教程集 >  脚本编程  >  java  >  正文 利用FindBugs减少代码中的bug数学习

利用FindBugs减少代码中的bug数学习

发布时间:2016-10-16   编辑:jiaochengji.com
教程集为您提供利用FindBugs减少代码中的bug数学习等资源,欢迎您收藏本站,我们将为您提供最新的利用FindBugs减少代码中的bug数学习资源
FindBugs 是一个静态分析工具,它检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。有了静态分析工具,就可以在不实际运行程序的情况对软件进行分析。

FindBugs 作用

开发人员在开发了一部分代码后,可以使用FindBugs进行代码缺陷的检查。提高代码的质量,同时也可以减少测试人员给你报的bug数。

静态分析工具承诺无需开发人员费劲就能找出代码中已有的缺陷。当然,如果有多年的编写经验,就会知道这些承诺并不是一定能兑现。
 
代码缺陷分类

根据缺陷的性质,大致可以分为下列几类

·Bad practice  不好的做法
·Correctness   可能有不正确
·Dodgy code     糟糕的代码
·Experimental  实验
·Internationalization  国际化
·Malicious code vulnerility 恶意的代码漏洞
·Multithreaded correctness 多线程问题
·Performance  性能问题

 FindBugs官方网站上也给出了一些案例:

http://findbugs.sourceforge.net/bugDescriptions.html

 怎么使用FindBugs?

使用FindBugs时,可以有3种方式:1)使用GUI、2)作用IDE的插件使用、3)在Ant脚本中使用。

 下面就说说前两种使用方式:


1)使用FindBugs GUI

 
1.1 下载

下载地址:Linux: http://prdownloads.sourceforge.net/findbugs/findbugs-3.0.1.tar.gz?download

Windows:http://prdownloads.sourceforge.net/findbugs/findbugs-3.0.1.zip?download

 1.2 安装

安装方式很简单,只用解压即可。安装后配置环境变量FINDBUGS_HOME。

Linux: export FINDBUGS_HOME=/home/username/findbugs

Windows:



1.3 启动

目录切换到findbugs/bin目录:

cd $findbugs_home/bin 或者 cd %findbugs_home%/bin

运行findbugs脚本:

./findbugs 或者 findbugs.bat

这样就可以启动findbugs GUI:

 
说明:

·要分析的类包和目录,一般是要分析的classes包

·辅助类就是依赖的jar包等

·源文件目录就是源码所在目录

 2)作为IDE插件使用

开发人员常用这种方式。支持的IDE有:Eclipse、NetBeans、Intellij IEDA。

下面就说说在Eclipse中如何使用了。

 下载插件

下载地址:http://sourceforge.net/projects/findbugs/files/findbugs eclipse plugin/

 安装

直接解压到eclipse/plugins目录下就行了。


 

 过滤器配置

打开Eclipse的Perferences配置:


 
分析bugs:

 



findBugs学习小结


今天代码质量再次强调java代码提交SVN前要经过findBugs检查,虽然根据菜单我也基本会有findBugs插件,但为了更全面的学习、更高效的利用,我搜索学习了findbugs的用法。


检查原理

Findbugs是一个静态分析工具,它检查类或者JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。Findbugs自带检测器,其中有60余种Bad practice,80余种Correctness,1种 Internationalization,12种Malicious code vulnerability,27种Multithreaded correctness,23种Performance,43种Dodgy。我们还可以自己配置检查规则(做哪些检查,不做哪些检查),也可以自己来实现独有的校验规则(用户自定义特定的bug模式需要继承它的接口,编写自己的校验类,属于高级技巧)。

 白盒测试中的静态检查一般是检查编码标准规范,错误列表。编码规范往往团队会根据自己的经验和风格进行设置一些规范。现在很多IDE工具都会在编辑代码的时候实时的提醒是否符合代码风格。错误列表,一般是代码潜在的bug,由于某种代码写法虽然没有语法错误,但是可能存在错误,比如会导致线程死锁。这些都是错误列表应该检查的。静态检查的可操作方式:

 1、代码走查:

  程序员之间可以隔一定的时间抽取代码进行走查。
  走查的时候根据汇总报告,把这些经验汇成列表,作为下次代码走查的依据。
  该方式的特点是,手工、多人讨论、操作简单,但是效率会比较低。

 2、代码扫描

使用软件对我们的代码进行扫描,查找出潜在的问题。现在有许多商业的工具能够进行扫描,比如Parasoft JTest、Software Analyzer、pclint等工具,往往不同的工具会针对不同的语言。当然也有很多开源的工具。在这里java方面主要推荐Findbugs。Findbugs可以在ANT/GUI/ECLIPSE三个环境中运行,同时也可以编写自己的检测器,功能比较完善。我们平时可以收集自己的或者是别人的开发经验,把它做成检测器来完善Findbugs的检测体系。软件扫描的特点是,机器扫描、效率高,但是没不够灵活,扩展比较负责。


Java静态检查工具对比

<table><tbody valign="top"><tr class="firstRow"><td style="border-top: outset 0.75pt; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt">

<span style="font-family:宋体; font-size:12pt">工具</span>

</td><td style="border-top: outset 0.75pt; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt">

<span style="font-family:宋体; font-size:12pt">目的</span>

</td><td style="border-top: outset 0.75pt; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt">

<span style="font-family:宋体; font-size:12pt">检查项</span>

</td></tr><tr><td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt" valign="middle">

<span style="font-family:宋体; font-size:12pt">FindBugs </span>

<span style="font-family:宋体; font-size:12pt">检查.class</span>

</td><td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt" valign="middle">

<span style="font-family:宋体; font-size:12pt">基于Bug Patterns概念,查找javabytecode(.class文件)中的潜在bug</span>

</td><td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt">

<span style="font-family:宋体; font-size:12pt">主要检查bytecode中的bug patterns,如NullPoint空指针检查、没有合理关闭资源、字符串相同判断错(==,而不是equals)等</span>

</td></tr><tr><td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt" valign="middle">

<span style="font-family:宋体; font-size:12pt">PMD </span>

<span style="font-family:宋体; font-size:12pt">检查源文件</span>

</td><td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt" valign="middle">

<span style="font-family:宋体; font-size:12pt">检查Java源文件中的潜在问题</span>

</td><td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt">

<span style="font-family:宋体; font-size:12pt">主要包括:</span>

<span style="font-family:宋体; font-size:12pt">空try/catch/finally/switch语句块</span>

<span style="font-family:宋体; font-size:12pt">未使用的局部变量、参数和private方法</span>

<span style="font-family:宋体; font-size:12pt">空if/while语句</span>

<span style="font-family:宋体; font-size:12pt">过于复杂的表达式,如不必要的if语句等</span>

<span style="font-family:宋体; font-size:12pt">复杂类</span>

</td></tr><tr><td style="border-top: none; border-left: outset 0.75pt; border-bottom: outset 0.75pt; border-right: outset 0.75pt" valign="middle">

<span style="font-family:宋体; font-size:12pt">CheckStyle </span>

<span style="font-family:宋体; font-size:12pt">检查源文件 </span>

<span style="font-family:宋体; font-size:12pt">主要关注格式</span>

</td><td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt" valign="middle">

<span style="font-family:宋体; font-size:12pt">检查Java源文件是否与代码规范相符</span>

</td><td style="border-top: none; border-left: none; border-bottom: outset 0.75pt; border-right: outset 0.75pt">

<span style="font-family:宋体; font-size:12pt">主要包括:</span>

<span style="font-family:宋体; font-size:12pt">Javadoc注释</span>

<span style="font-family:宋体; font-size:12pt">命名规范</span>

<span style="font-family:宋体; font-size:12pt">多余没用的Imports</span>

<span style="font-family:宋体; font-size:12pt">Size度量,如过长的方法</span>

<span style="font-family:宋体; font-size:12pt">缺少必要的空格Whitespace</span>

<span style="font-family:宋体; font-size:12pt">重复代码</span>

</td></tr></tbody></table>



使用及配置

本文主要介绍在Eclipse中使用的情况

FindBugs是一个可以在Java程序中发现Bugs的程序。它是专门用来寻找处于"Bug Patterns"列表中的代码的。Bug Patterns指很有可能是错误的代码的实例。

打开Bug Details视图Windows => Show View => Other… => FindBugs => BugDetails


在Package Explorer或Navigator视图中,选中你的Java项目,右键,可以看到"Find Bugs"菜单项,子菜单项里有"Find Bugs"和"Clear Bug Markers"两项内容,如下图所示:

我们建立一个简单的测试文件Test.java 内容如下:

<pre class="brush:java;toolbar:false">public class Test { private String[] name; public String[] getName() { return name; } public void setName(String[] name) { this.name = name; } }</pre>


我们点中"Find Bugs",运行时会出现如下进度框:

运行结束后可以在Problems中看到增加了如下的警告信息内容

FindBugs运行后的警告信息内容不仅在Problems视图中显示,而且将标记在源代码标记框中,在源代码编辑器中我们可以看到警告标识,如下图:


当光标指向你的警告信息的代码上面时,就会有相应的错误提示信息,与Eclipse本身的错误或警告信息提示类似。

选中Problems视图里出现的相应问题,就会在代码编辑器里切换到相应的代码上去,方便根据相应的提示信息进行代码的修改。


在Problems视图里,选中相应的问题条目,右键,在弹出的菜单中,可以看到"Show Bug Details",如下图所示:


点中它,会切换到Bug Details视图上去,显示更加详细的提示信息。

当然,在代码编辑窗口中,点击带有警告提示信息的图标时,也会自动切换到Bud Details窗口去,查看详细的警告信息,如下图所示。


根据这里详细的信息,你可以得到FindBugs为什么会对你的代码报警告信息,及相应的处理办法,根据它的提示,你可以快速方便地进行代码修改。

根据提示,我们将代码修改成如下,再运行就不会报有警告信息了。

<pre class="brush:java;toolbar:false">public class Test { private String[] name; public String[] getName() { String[] temp = name; return temp; } public void setName(String[] name) { String[] temp = name; this.name = temp; } }</pre>


配置FindBugs

选择你的项目,右键 => Properties => FindBugs =>


可以配置的信息包括如上图所示的四个选项的相关设置:

1. Run FindBugs Automatically开关

当此项选中后,FindBugs将会在你修改Java类时自动运行,如你设置了Eclipse自动编译开关后,当你修改完Java文件保存,FindBugs就会运行,并将相应的信息显示出来。

当此项没有选中,你只能每次在需要的时候自己去运行FindBugs来检查你的代码。

2. Minimum priority to report选择项

这个选择项是让你选择哪个级别的信息进行显示,有Low、Medium、High三个选择项可以选择,很类似于Log4J的级别设置啦。 比如:

你选择了High选择项,那么只有是High级别的提示信息才会被显示。

你选择了Medium选择项,那么只有是Medium和High级别的提示信息才会被显示。

你选择了Low选择项,那么所有级别的提示信息都会被显示。

3. Enable bug categories选择项

在这里是一些显示Bug分类的选择:

Correctness关于代码正确性相关方面的

Performance关于代码性能相关方面的

Internationalization关于代码国际化相关方面的

Multithreaded correctness关于代码多线程正确性相关方面的

Style关于代码样式相关方面的

Malicious code vulnerability关于恶意破坏代码相关方面的

比如:如果你把Style的检查框去掉不选择中它,那么与Style分类相关的警告信息就不会显示了。其它的类似。

4. Select bug patterns to check for选择项

在这里你可以选择所要进行检查的相关的Bug Pattern条目

可以从Bug codes、Detector name、Detector description中看到相应的是要检查哪些方面的内容,你可以根据需要选择或去掉相应的 检查条件。

三、详细说明

Findbugs是一个静态分析工具,它检查类或者JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。Findbugs自带检测器,其中有60余种Bad practice,80余种Correctness,1种 Internationalization,12种Malicious code vulnerability,27种Multithreaded correctness,23种Performance,43种Dodgy。

Bad practice 坏的实践

一些不好的实践,下面列举几个:

HE: 类定义了equals(),却没有hashCode();或类定义了equals(),却使用

Object.hashCode();或类定义了hashCode(),却没有equals();或类定义了hashCode(),却使用Object.equals();类继承了equals(),却使用Object.hashCode()。

SQL:Statement 的execute方法调用了非常量的字符串;或Prepared Statement是由一个非常量的字符串产生。

DE: 方法终止或不处理异常,一般情况下,异常应该被处理或报告,或被方法抛出。

Correctness 一般的正确性问题

可能导致错误的代码,下面列举几个:

NP: 空指针被引用;在方法的异常路径里,空指针被引用;方法没有检查参数是否null;null值产生并被引用;null值产生并在方法的异常路径被引用;传给方法一个声明为@NonNull的null参数;方法的返回值声明为@NonNull实际是null。

Nm: 类定义了hashcode()方法,但实际上并未覆盖父类Object的hashCode();类定义了tostring()方法,但实际上并未覆盖父类Object的toString();很明显的方法和构造器混淆;方法名容易混淆。

SQL:方法尝试访问一个Prepared Statement的0索引;方法尝试访问一个ResultSet的0索引。

UwF:所有的write都把属性置成null,这样所有的读取都是null,这样这个属性是否有必要存在;或属性从没有被write。

Internationalization 国际化

当对字符串使用upper或lowercase方法,如果是国际的字符串,可能会不恰当的转换。

Malicious code vulnerability 可能受到的恶意攻击

如果代码公开,可能受到恶意攻击的代码,下面列举几个:

FI: 一个类的finalize()应该是protected,而不是public的。

MS:属性是可变的数组;属性是可变的Hashtable;属性应该是package protected的。

Multithreaded correctness 多线程的正确性

多线程编程时,可能导致错误的代码,下面列举几个:

ESync:空的同步块,很难被正确使用。
MWN:错误使用notify(),可能导致IllegalMonitorStateException异常;或错误的

使用wait()。

No: 使用notify()而不是notifyAll(),只是唤醒一个线程而不是所有等待的线程。
SC: 构造器调用了Thread.start(),当该类被继承可能会导致错误。

Performance 性能问题

可能导致性能不佳的代码,下面列举几个:

DM:方法调用了低效的Boolean的构造器,而应该用Boolean.valueOf(…);用类似
Integer.toString(1) 代替new Integer(1).toString();方法调用了低效的float的构造器,应该用静态的valueOf方法。

SIC:如果一个内部类想在更广泛的地方被引用,它应该声明为static。
SS: 如果一个实例属性不被读取,考虑声明为static。
UrF:如果一个属性从没有被read,考虑从类中去掉。
UuF:如果一个属性从没有被使用,考虑从类中去掉。

Dodgy 危险的

具有潜在危险的代码,可能运行期产生错误,下面列举几个:

CI: 类声明为final但声明了protected的属性。
DLS:对一个本地变量赋值,但却没有读取该本地变量;本地变量赋值成null,却没有读取该本地变量。
ICAST: 整型数字相乘结果转化为长整型数字,应该将整型先转化为长整型数字再相乘。
INT:没必要的整型数字比较,如X <= Integer.MAX_VALUE。
NP: 对readline()的直接引用,而没有判断是否null;对方法调用的直接引用,而方法可能返回null。
REC:直接捕获Exception,而实际上可能是RuntimeException。
ST: 从实例方法里直接修改类变量,即static属性。

您可能感兴趣的文章:
利用FindBugs减少代码中的bug数学习
python初学用什么工具
初学python用什么编译器
初学python用什么编辑器好
为什么都不用 switch 而使用 if/ else 来做条件判断?
Javascript的循环优化探究
PHP多久能学会?
php获取网站ico
学习j2ee流程
为什么程序员都不喜欢使用 switch ,而是大量的 if……else if ?

[关闭]
~ ~