Findbugs使用手册

Findbugs 是一个在 java 程序中查找 bug 的程序,它查找 bug 模式的实例,也就是可能出错的代码实例,注意 Findbugs 是检查 java 字节码,也就是 *.class 文件。其实 准确的说,它是寻找代码缺陷的,很多我们写的不好的地方,可以优化的地方,它都能检查出来。例如:未关闭的数据库连接,缺少必要的 null check ,多余的 null check ,多余的 if 后置条件,相同的条件分支,重复的代码块,错误的使用了 "==" ,建议使用 StringBuffer 代替字符串连加等等。而且我们还可以自己配置检查规则 ( 做哪些检查 , 不做哪些检查 ) ,也可以自己来实现独有的校验规则 ( 用户自定义特定的 bug 模式需要继承它的接口 , 编写自己的校验类 , 属于高级技巧 )

 

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 属性。

 

1、 Ant 配合使用

http://findbugs.sourceforge.net/downloads.html 下载最新版本的 Findbugs ,目前的版本是 1.3.0 , 2007 11 8 发布。把解压后目录复制到项目的 lib 目录下,然后就可以和 Ant 配合使用了。 FindBugs 工作在 j2se1.4.0 或以后的版本中,需要至少 256MB 内存。

Ant 脚本中,首先定义 Findbugs 的解压目录位置:

<path id= "findbugs.path" >

      <fileset   dir = "${lib.home}/findbugs-1.3.0" >

        <include   name = "**/*.jar" />

      </fileset>

</path>

接着声明 Findbugs 任务:

<taskdef name= "findbugs"  

classname= "edu.umd.cs.findbugs.anttask.FindBugsTask"  

classpathref = "findbugs.path" />

然后建立 Findbugs 任务:

<property name = "findbugs.home"   value = "${lib.home}/findbugs-1.3.0" />

<!--  定义 findbugs home findbugs task 要使用   -->

<target name = "findbugs" >

<findbugs home = "${findbugs.home}" includeFil ter="${findbugs_include_filter}"

excludeFilter ="${findbugs_exclude_filter}"

  jvmargs= "-Xmx384m"   output = "html"  

outputFile = "d:/test.html" >

            <class location = "${build.home}/WEB-INF/classes/" />

             <!--  以上定义 findbugs 查找的类路径   -->

<auxClasspath path ="${lib.home}/findbugs-1.3.0/lib/findbugs-ant.jar" />

            <auxClasspath>

           <fileset dir= "${build.home}/WEB-INF/lib" includes= "**/*.jar" />

             </auxClasspath>

             <!--  以上定义上述类所依赖的类路径   -->

             <sourcePath path = "${src.home}" />

            <!--  以上定义源代码的路径   -->

          </findbugs >

</target >

最后运行 ant findbugs 即可。

 

2、Eclipse 插件

Eclipse 当中安装 Findbugs 插件和安装 CheckStyle 一样,可以参照以下五个步骤进行:

a.       Eclipse 当中分别打开一下菜单 Help->Software Updates->Find and Install

b.       选择 Search for new features to install 选项然后点击 Next

c.       新建一个 New Remote Site...

d.       输入名称(比如: Findbugs Plug-in )和下面的 URL http://findbugs.cs.umd.edu/eclipse

e.       开始安装

    安装好 Findbugs 以后,选择 Windows -> Show View -> Other… -> FindBugs -> BugDetails 打开 Bug Details 视图。

    然后在 Package Explorer Navigator 视图中,选中你的 Java 项目,点击右键,可以看到 “Find Bugs” 菜单项,子菜单项里有 “Find Bugs” “Clear Bug Markers” 两项内容。

    我们点中 “Find Bugs” ,运行结束后可以在 Problems 中看到增加了如下的警告信息内容。(图略)

    FindBugs 运行后的警告信息内容不仅在 Problems 视图中显示,而且将标记在源代码标记框中,在源代码编辑器中我们可以看到警告标识, 当光标指向你的警告信息的代码上面时,就会有相应的错误提示信息,与 Eclipse 本身的错误或警告信息提示类似。
    选中 Problems 视图里出现的相应问题,就会在代码编辑器里切换到相应的代码上去,方便根据相应的提示信息进行代码的修改。

    在 Problems 视图里,选中相应的问题条目,右键,在弹出的菜单中,可以看到 “Show Bug Details”。

       点中它,会切换到 Bug Details 视图上去,显示更加详细的提示信息。 当然,在代码编辑窗口中,点击带有警告提示信息的图标时,也会自动切换到 Bug Details 窗口去,查看详细的警告信息。

    选择你的项目,右键点击 Properties ,选择 FindBugs 可以配置 Findbugs 的一些选项。

 

3、   使用过滤器

使用过滤器我们就可以定义使用哪些 bug 检测器和针对哪些类进行检查,因为一旦项目比较庞大,那查看冗长的 bug 报告也是十分痛苦的事情。使用过滤器,过滤器用来包含或排除特殊的 bug 报告。这样做有助于在特定的时间段内,聚焦我们的关注点。过滤器实际是在一个 xml 文件定义的, xml 配置文件的内容如下:

< FindBugsFilter >

     <!--  所有类使用 bugcode HE 的检测器   -->

     < Match >

         < BugCode  name = "HE" />

     </ Match >

     <!--  该类使用所有的 bug 检测器   -->

     < Match class = "com.foobar.AClass" />     

     <!--  该类使用 bugcode HE 的检测器   -->

     < Match class = "com.foobar.BClass" >

         < BugCode  name = "HE" />

     </ Match >

     <!--  该类的 AMethod BMethod 方法使用 bugcode HE 的检测器   -->

     < Match class = "com.foobar.CClass" >

         < Or >

             < Method name = "AMethod" />

             < Method name = "BMethod" />

         </ Or >

         < BugCode name = "HE" />

     </ Match >

</ FindBugsFilter >

 

4、Findbugs过滤器的一些元素讲解:

<FindBugsFilter>

     <!--  该类使用所有的 bug 检测器   -->

     <Match>

       <Class name="com.foobar.MyClass" />

     </Match>  

     <!--  该类使用 bugcode HE 的检测器   -->

     <Match class ="com.foobar.BClass">

         <BugCode  name ="HE"/>

     </Match>

     <!--  该类通过指定缩写名使用一些 bug 检测器   -->

     <Match>

       <Class name="com.foobar.MyClass"/ >

       <Bug code="DE,UrF,SIC" />

     </Match>

     <!--  所有类使用 bugcode HE 的检测器   -->

     <Match>

         <BugCode  name ="HE"/>

     </Match>

     <!--  所有类使用 bugcode DE,UrF,SIC 的检测器   -->

     <Match>

       <Bug code="DE,UrF,SIC" />

     </Match>

     <!--  所有类通过指定检测器种类使用某些检测器   -->

      <Match>

       <Bug category="PERFORMANCE" />

     </Match>

     <!--  该类的指定方法使用 bugcode DC 的检测器   -->

      <Match>

       <Class name="com.foobar.MyClass" />

       <Or>

       <Method name="frob" params="int,java.lang.String" returns="void" />

       <Method name="blat" params="" returns="boolean" />

       </Or>

       <Bug code="DC" />

     </Match>

     <!--  该类的 AMethod BMethod 方法使用 bugcode DE,UrF,SIC 的检测器   -->

     <Match>

          <Class name="com.foobar.MyClass" />

         <Or>

             <Method name ="AMethod"/>

              <Method name ="BMethod"/>

         </Or>

         <BugCode name ="DE,UrF,SIC "/>

     </Match>

       <!— 该类的指定方法使用 bug 模式为 OS_OPEN_STREAM 的检测器 -->

      <Match>

         <Class name="com.foobar.MyClass" />

         <Method name="writeDataToFile" />

         <Bug pattern="OS_OPEN_STREAM" />

       </Match>

    <!— 该类的某个方法使用优先级为 2 bug 模式 DLS_DEAD_LOCAL_STORE 的检测器 -->

    <Match>

      <Class name="com.foobar.MyClass" />

      <Method name="someMethod" />

      <Bug pattern="DLS_DEAD_LOCAL_STORE" />

      <Priority value="2" />

    </Match>

     <!— 代码的指定部分使用指定 bugcode bug 模式的检测器 -->

    <!— 所有包的信息类使用 bugcode UUF 的检测器 -->

    <Match>

      <Class name="~.*/.Messages" />

      <Bug code="UUF" />

    </Match>

    <!— 所有内部包使用 bugcode MS 的检测器 -->

    <Match>

      <Package name="~.*/.internal" />

      <Bug code="MS" />

    </Match>

    <!—ui 包层使用 bug 模式为 SIC_INNER_SHOULD_BE_STATIC_ANON 的检测器 -->

    <Match>

      <Package name="~com/.foobar/.fooproject/.ui.*" />

      <Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON" />

    </Match>

    <!— 带指定标志的成员域或方法使用指定 bugcode bug 模式的检测器 -->

    <!— 所有类中的 void main(String[]) 方法使用 bug 模式为 DM_EXIT 的检测器 -->

    <Match>

      <Method returns="void" name="main" params="java.lang.String[]" />

      <Bug pattern="DM_EXIT" />

    </Match>

    <!— 所有类中的 com.foobar.DebugInfo 型的域使用 bugcode UuF 的检测器 -->

    <Match>

      <Field type="com.foobar.DebugInfo" />

      <Bug code="UuF" />

    </Match>

</FindBugsFilter>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值