现在的位置: 首页 > 综合 > 正文

静态代码检查工具 FindBugs 详解eclipse插件findbugs新规则的开发过程

2013年09月20日 ⁄ 综合 ⁄ 共 9858字 ⁄ 字号 评论关闭

 

静态代码检查工具 FindBugs
使用 FindBugs的原因和方法
 
静态分析工具承诺无需开发人员费劲就能找出代码中已有的缺陷。当然,如果有多年的编写经验,就会知道这些承诺并不是一定能兑现。尽管如此,好的静态分析工具仍然是工具箱中的无价之宝。在这个由两部分组成的系列文章的第一部分中,高级软件工程师 Chris
Grindstaff
分析了 FindBugs如何帮助提高代码质量以及排除隐含的缺陷。
代码质量工具的一个问题是它们容易为开发人员提供大量但并非真正问题的问题——伪问题(false
positives
。出现伪问题时,开发人员要学会忽略工具的输出或者放弃它。FindBugs的设计者
David Hovemeyer
William Pugh注意到了这个问题,并努力减少他们所报告的伪问题数量。与其他静态分析工具不同,FindBugs不注重样式或者格式,它试图只寻找真正的缺陷或者潜在的性能问题。
FindBugs是什么?
FindBugs是一个静态分析工具,它检查类或者 JAR文件(注意它分析是不是JAVA源文件而是编绎后CLASS类),将字节码与一组缺陷模式进行对比以发现可能的问题。有了静态分析工具,就可以在不实际运行程序的情况对软件进行分析。不是通过分析类文件的形式或结构来确定程序的意图,而是通常使用
Visitor
模式(请参阅参考资料)。图
1
显示了分析一个匿名项目的结果(为防止可怕的犯罪,这里不给出它的名字):
1. FindBugs UI
 

2.安装Eclipse的FindBugs插件

可以在下面的地址

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

打开页面内容如下:

下载FindBugs软件以及eclipse和blueJ的插件。

The Eclipse plugin may also be obtained from one of the FindBugs Eclipse plugin update sites: --FindBugs插件的更新地址有很多,根据类型的不同,包括以下几个:

单击上面链接即可下载(另存).

也可以在下面的地址:

http://prdownloads.sourceforge.net/findbugs

下载插件的zip文件,将其解压缩到eclipse的plugin目录(<eclipse_install_dir>/plugins)。

安装完插件后,可以使用Help-->About Eclipse Platform-->Plug-in Details来查看FindBugs插件的使用方法。

3.       在Eclipse中使用FindBugs插件

运行FindBugs插件的方法很简单,选中一个Java工程后,点击右键,选择Find Bugs,这时就会启动FindBugs,并且会在有问题的源代码中显示标记。

可以自定义FindBugs的运行方式:查看Java工程的属性对话框,选择FindBugs的属性页,可以看到如下的选项:

→       启用/禁用”自动运行FindBugs”复选框---是否在每次修改时进行FindBugs的检查

→       选择最小的警告优先级,并启用bug的分类---这些选项用于决定显示哪些问题,例如,如果选择Medium警告优先级的话,只有Medium和Hign优先级的警告才会被显示,类似的,如果不选中Style复选框的话,那么有关Style类别的警告也不会被显示。

→       选择检查引擎:对指定的工程启用那些detectors。

具体的设置画面如下:


(设置detectors和是否自动运行FindBugs)


(设置启用的分类)

 

常见的类型如下:

· 正确性(Correctness):这种归类下的问题在某种情况下会导致bug,比如错误的强制类型转换等。

· 最佳实践反例(Bad practice):这种类别下的代码违反了公认的最佳实践标准,比如某个类实现了equals方法但未实现hashCode方法等。

· 多线程正确性(Multithreaded correctness):关注于同步和多线程问题。

· 性能(Performance):潜在的性能问题。

· 安全(Security):安全相关。

· 高危(Dodgy):FindBugs团队认为该类型下的问题代码导致bug的可能性很高。

在Eclipse中安装FindBugs插件

   下载Eclipse plugin 的版本,解压zip文件。

   将解压后的文件放到Eclipse的Plugin中。

   重新启动Eclipse 。

 

    我使用的是MyEclipse8.5可能路径和大家的不太一样,我是放到了路径Genuitec/MyEclipse 8.5/dropins下面 

 

在Eclipse中使用FindBugs

重新启动eclipse

打开FindBugs视图 

 

执行Find Bug 任务

右键单击你要检测的工程、包或文件,-->Find Bugs-->Find Bugs。

check完成后将在Bug Explorer视图中看到问题列表,该列表以问题类型组织。 

 

展开列表,双击列表中具体的问题就可以定位的具体的代码行。 

配置FindBugs
在这里可以对FindBugs规则等进行详细设置。 
  选择你的项目,右键 => Properties => FindBugs =>

 

1 Run Automatically开关

设置Eclipse自动编译开关-----即主窗口菜单Project---Build Automatically这个选项勾上就行了.

当此项选中后,FindBugs将会在你修改Java类时自动运行,如你设置了Eclipse自动编译开关后,当你修改完Java文件保存,FindBugs就会运行,并将相应的信息显示出来。
当此项没有选中,你只能每次在需要的时候自己去运行FindBugs来检查你的代码。

2 Detector Configuration选择项
在这里你可以选择所要进行检查的相关的Bug Pattern条目,你可以根据需要选择或去掉相应的 检查条件。 

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

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

4 Report bug categories选择项
在这里是一些显示Bug分类的选择:
Malicious code vulnerability关于恶意破坏代码相关方面的
Correctness关于代码正确性相关方面的
Internationalization关于代码国际化相关方面的
Performance关于代码性能相关方面的
Multithreaded correctness关于代码多线程正确性相关方面的

另外FindBugs有UI页面,可以单独运行。也可以通过Ant以及命令行方式运行。

 

 

4.       在Ant中使用FindBugs

Ant作为一个优秀的自动化构建软件,大量的应用在Java软件开发中(虽然有被Maven取代的危险)。FindBugs提供了集成在Ant中使用的Ant Task,可以在自动构建与部署的时候运行FindBugs。

将$FINDBUGS_HOME/lib/findbugs-ant.jar拷贝到$ANT_HOME/lib目录下以后,就完成了FindBugs的Ant Task的安装。(强烈建议使用FindBugs附带的jar文件)

为了将FindBugs任务集成到Ant脚本中,需要首先进行一个task的定义,如下面的片段所示:---下面ANT的XML内容介绍

<taskdef name=”findbugs” classname=”edu.umd.cs.findbugs.anttask.FindBugsTask” />

在定义了findbugs task之后,就可以使用了。下面是一个例子:

<property name="findbugs.home" value="/export/home/daveho/work/findbugs" /> 

<target name="findbugs" depends="jar">

<findbugs home="${findbugs.home}"

      output="xml"

      outputFile="bcel-fb.xml" >

<auxClasspath path="${basedir}/lib/Regex.jar" />

<sourcePath path="${basedir}/src/java" />

<class location="${basedir}/bin/bcel.jar" />

</findbugs>

</target>

findbugs元素必须有home属性,用于指定FindBugs的安装路径。

这是就会在bcel.jar上执行FindBugs。FindBugs的运行结果会被以xml的格式保存在bcel-fb.xml文件中。一个辅助的jar文件被添加到auxClasspath元素中,因为BCEL库引用了它。

另外一个例子:

从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}" includeFilter="${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即可。  

使用过滤器         

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

<FindBugsFilter>          

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

     <Match>          

         <BugCode  name ="HE"/>          

     </Match>          

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

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

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

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

         <BugCode  name ="HE"/>         

     </Match>         

     <!--  该类的AMethodBMethod方法使用bugcodeHE的检测器  -->         

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

         <Or>         

             <Method name ="AMethod"/>          

             <Method name ="BMethod"/>          

         </Or>          

         <BugCode name ="HE"/>          

     </Match>          

</FindBugsFilter>     

        

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

<FindBugsFilter>          

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

     <Match>         

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

     </Match>            

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

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

         <BugCode  name ="HE"/>          

     </Match>          

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

     <Match>         

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

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

     </Match>         

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

     <Match>          

         <BugCode  name ="HE"/>         

     </Match>          

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

     <Match>         

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

     </Match>         

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

     <Match>         

       <Bug category="PERFORMANCE" />         

     </Match>         

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

     <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>         

     <!--  该类的AMethodBMethod方法使用bugcodeDE,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>         

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

    <Match>         

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

      <Method name="someMethod" />         

      <Bug pattern="DLS_DEAD_LOCAL_STORE" />         

      <Priority value="2" />         

    </Match>         

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

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

    <Match>          

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

      <Bug code="UUF" />        

    </Match>         

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

    <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>         

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

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

    <Match>         

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

抱歉!评论已关闭.