Grindstaff 分析了 FindBugs如何帮助提高代码质量以及排除隐含的缺陷。
positives)。出现伪问题时,开发人员要学会忽略工具的输出或者放弃它。FindBugs的设计者
David Hovemeyer和 William Pugh注意到了这个问题,并努力减少他们所报告的伪问题数量。与其他静态分析工具不同,FindBugs不注重样式或者格式,它试图只寻找真正的缺陷或者潜在的性能问题。
Visitor模式(请参阅参考资料)。图
1显示了分析一个匿名项目的结果(为防止可怕的犯罪,这里不给出它的名字):
2.安装Eclipse的FindBugs插件
可以在下面的地址
http://findbugs.sourceforge.net/downloads.html
打开页面内容如下:
下载FindBugs软件以及eclipse和blueJ的插件。
- FindBugs tool (standard version with command line, ant, and Swing interfaces)
- findbugs-1.3.9.tar.gz
- findbugs-1.3.9.zip ----WINDOWS下载FindBugs软件,可独立运行.并可在Ant中使用FindBugs
- findbugs-1.3.9-source.zip
- Eclipse plugin for FindBugs version 1.3.9.20090821 (requires Eclipse 3.3 or later)
- edu.umd.cs.findbugs.plugin.eclipse_1.3.9.20090821.zip --------eclipse 的FindBugs插件,不能独立运行,只能集成到eclipse插件运行
- eclipsePlugin-1.3.9.20090821-source.zip
The Eclipse plugin may also be obtained from one of the FindBugs Eclipse plugin update sites: --FindBugs插件的更新地址有很多,根据类型的不同,包括以下几个:
- http://findbugs.cs.umd.edu/eclipse update site for official releases ---只提供FindBugs的官方释放版本。
- http://findbugs.cs.umd.edu/eclipse-candidate update site for candidate releases and official releases --提供FindBugs的官方释放版本和可选释放版本。
- http://findbugs.cs.umd.edu/eclipse-daily update site for all releases, including developmental ones --提供最新的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>
<!-- 所有类使用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>
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[]" />