??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美黄色网页,精品久久久久久亚洲精品,亚洲一区二区三区四区中文http://www.aygfsteel.com/hulizhong/category/39077.html----Java's Slave----<br> ***Java's Host***zh-cnThu, 16 Apr 2009 07:27:37 GMTThu, 16 Apr 2009 07:27:37 GMT60?FindBugsQ第 1 部分: 提高代码质量http://www.aygfsteel.com/hulizhong/archive/2009/04/16/265948.html二胡二胡Thu, 16 Apr 2009 05:12:00 GMThttp://www.aygfsteel.com/hulizhong/archive/2009/04/16/265948.htmlhttp://www.aygfsteel.com/hulizhong/comments/265948.htmlhttp://www.aygfsteel.com/hulizhong/archive/2009/04/16/265948.html#Feedback0http://www.aygfsteel.com/hulizhong/comments/commentRss/265948.htmlhttp://www.aygfsteel.com/hulizhong/services/trackbacks/265948.html

FindBugsQ第 1 部分: 提高代码质量

使用 FindBugs 的原因和Ҏ(gu)

developerWorks
文档选项

未显C需?JavaScript 的文档选项

打印机的版面设|成横向打印模式

打印本页

此作为电(sh)子邮件发? vspace=

此作为电(sh)子邮件发?/strong>


U别Q?初

Chris Grindstaff (chris@gstaff.org), 软g工程?br />

2004 q? 5 ? 25 ?/p>

? 态分析工h诺无需开发h员费劲就能找Z码中已有的缺陗当Ӟ如果有多q的~写l验Q就会知道这些承诺ƈ不是一定能兑现。尽如此,好的静态分析工? 仍然是工L中的无h(hun)之宝。在q个׃部分l成的系列文章的W一部分中,高软g工程?Chris Grindstaff 分析?FindBugs 如何帮助提高代码质量以及排除隐含的缺陗?/blockquote>

代码质量工具的一个问题是它们Ҏ(gu)为开发h员提供大量但q真正问题的问题——即 伪问题(false positivesQ?/em>? 出现伪问题时Q开发h员要学会忽略工具的输出或者放弃它。FindBugs 的设计?David Hovemeyer ?William Pugh 注意Cq个问题Qƈ努力减少他们所报告的伪问题数量。与其他静态分析工具不同,FindBugs 不注重样式或者格式,它试囑֏L真正的缺h者潜在的性能问题?

FindBugs 是什么?

FindBugs 是一个静态分析工P它检查类或?JAR 文gQ将字节码与一l缺h式进行对比以发现可能的问题。有了静态分析工P可以在不实际运行程序的情况对Y件进行分析。不是通过分析cL件的形式或结 构来定E序的意图,而是通常使用 Visitor 模式Q请参阅 参考资?/a>Q。图 1 昄了分析一个匿名项目的l果Qؓ防止可怕的犯罪Q这里不l出它的名字Q:


?1. FindBugs UI
Configure Detector 的图形表C? src=

让我们看几个 FindBugs 可以发现的问题?/p>

本系列的W二文?#8220; ~写自定义检器”解释了如何编写自定义器Q?以便发现特定于应用程序的问题?





回页?/strong>


问题发现的例?/span>

下面的列表没有包?FindBug 可以扑ֈ? 所?/em>问题。相反,我侧重于一些更有意思的问题?

器Q找?hash equals 不匹?/strong>
q个器L? equals() ? hashCode() 的实现相关的几个问题。这两个Ҏ(gu)非常重要Q因为几乎所有基于集合的cZ?List、Map、Set {都调用它们。一般来_q个器L两种不同cd的问题——当一个类Q?

  • 重写对象? equals() Ҏ(gu)Q但是没有重写它? hashCode Ҏ(gu)Q或者相反的情况时?

  • 定义一?co-variant 版本? equals() ? compareTo() Ҏ(gu)。例如, Bob cd义其 equals() Ҏ(gu)为布?yu)? equals(Bob) Q它覆盖了对象中定义? equals() Ҏ(gu)。因?Java 代码在编译时解析重蝲Ҏ(gu)的方式,在运行时使用的几乎L在对象中定义的这个版本的Ҏ(gu)Q而不是在 Bob 中定义的那一个(除非昑ּ? equals() Ҏ(gu)的参数强制{换ؓ Bob cdQ。因此,当这个类的一个实例放入到c集合中的Q何一个中Ӟ使用的是 Object.equals() 版本的方法,而不是在 Bob 中定义的版本。在q种情况下, Bob cd当定义一个接受类型ؓ Object 的参数的 equals() Ҏ(gu)?

器Q忽略方法返回?/strong>
q个器查找代码中忽略了不应该忽略的Ҏ(gu)q回值的地方。这U情늚一个常见例子是在调? String Ҏ(gu)Ӟ如在清单 1 中:


清单 1. 忽略q回值的例子
1  String aString = "bob";
2 b.replace('b', 'p');
3 if(b.equals("pop"))

q个错误很常见。在W?2 行,E序员认Z已经?p 替换了字W串中的所?b。确实是q样Q但是他忘记了字W串是不可变的。所有这cL法都q回一个新字符Ԍ而从来不会改变消息的接收者?/p>

器QNull 指针?null 的解引用QdereferenceQ和冗余比较
q个器查找两类问题。它查找代码路径会或者可能造成 null 指针异常的情况,它还查找?null 的冗余比较的情况。例如,如果两个比较值都?nullQ那么它们就是冗余的q可能表明代码错误。FindBugs 在可以确定一个gؓ null 而另一个g?null Ӟ类似的错误Q如清单 2 所C:


清单 2. Null 指针CZ
1  Person person = aMap.get("bob");
2 if (person != null) {
3 person.updateAccessTime();
4 }
5 String name = person.getName();

在这个例子中Q如果第 1 行的 Map 不包括一个名?#8220;bob”的hQ那么在W?5 行询? person 的名字时׃出现 null 指针异常。因?FindBugs 不知?map 是否包含“bob”Q所以它?yu)?5 行标Cؓ可能 null 指针异常?

器Q初始化之前d字段
q个器L在构造函C初始化之前被d的字Dc这个错误通常是——尽不L如此——由使用字段名而不是构造函数参数引LQ如清单 3 所C:


清单 3. 在构造函Cd未初始化的字D?/strong>
1  public class Thing {
2 private List actions;
3 public Thing(String startingActions) {
4 StringTokenizer tokenizer = new StringTokenizer(startingActions);
5 while (tokenizer.hasMoreTokens()) {
6 actions.add(tokenizer.nextToken());
7 }
8 }
9 }

在这个例子中Q第 6 行将产生一?null 指针异常Q因为变? actions q没有初始化?

q些例子只是 FindBugs 所发现的问题种cȝ一部分(更多信息请参? 参考资?/a>Q。在撰写本文ӞFindBugs 提供d 35 个检器?





回页?/strong>


开始?FindBugs

要运?FindBugsQ需要一个版?1.4 或者更高的 Java Development Kit QJDKQ,管它可以分析由老的 JDK 创徏的类文g。要做的W一件事是下载ƈ安装最新发布的 FindBugs——当前是 0.7.1 Q请参阅 参考资?/a>Q。幸q的是,下蝲和安全是相当单的。在下蝲?zip 或?tar 文g后,它解压~到所选的目录中。就是这样了——安装就完成了?

? 装完后,对一个示例类q行它。就像一般文章中的情况,我将针对 Windows 用户q行讲解Qƈ假定那些 Unix 信Ԓ者可以熟l地转化q些内容q跟q。打开命o行提C符号ƈq入 FindBugs 的安装目录。对我来_q是 C:\apps\FindBugs-0.7.3?/p>

?FindBugs ȝ录中Q有几个值得注意的目录。文档在 doc 目录中,但是Ҏ(gu)们来说更重要的是Qbin 目录包含了运?FindBugs 的批处理文gQ这使我们进入下一部分?/p>



回页?/strong>


q行 FindBugs

? 如今的大多数数工具一P可以以多U方式运?FindBugs——从 GUI、从命o行、?Ant、作?Eclipse 插gE序和? Maven。我简要提及从 GUI q行 FindBugsQ但是重Ҏ(gu)在用 Ant 和命令行q行它。部分原因是׃ GUI 没有提供命o行的所有选项。例如,当前不能指定要加入的qo器或者在 UI 中排除特定的cR但是更重要的原因是我认?FindBugs 最好作为编译的集成部分使用Q?UI 不属于自动编译?/p>

使用 FindBugs UI

使用 FindBugs UI 很直观,但是有几点值得说明。如 ?1所C,使用 FindBugs UI 的一个好处是Ҏ(gu)一个检到的问题提供了说明。图 1 昄了缺? Naked notify in method的说明。对每一U缺h式提供了cM的说明,在第一ơ熟(zhn)这U工hq是很有用的。窗口下面的 Source code 选项卡也同样有用。如果告?FindBugs 在什么地方寻找代码,它就会在转换到相应的选项卡时H出昄有问题的那一行?

值得一提的q有在将 FinBugs 作ؓ Ant d或者在命o行中q行 FindBugs Ӟ选择 xml 作ؓ ouput 选项Q可以将上一ơ运行的l果装蝲?UI 中。这样做是同时利用基于命令行的工具和 UI 工具的优点的一个很好的Ҏ(gu)?

?FindBugs 作ؓ Ant dq行

? 我们看一下如何在 Ant ~译脚本中?FindBugs。首先将 FindBugs Ant d拯?Ant ?lib 目录中,q样 Ant q道新的Q务。将 FIND_BUGS_HOME\lib\FindBugs-ant.jar 拯?ANT_HOME\lib?/p>

现在看看在编译脚本中要加入什么才能?FindBugs d。因?FindBugs 是一个自定义dQ将需要? taskdef d以 Ant 知道装蝲哪一个类。通过在编译文件中加入以下一行做到这一点:

<taskdef name="FindBugs" classname="edu.umd.cs.FindBugs.anttask.FindBugsTask"/>

在定义了 taskdef 后,可以用它的名? FindBugs 引用它。下一步要在编译中加入使用CQ务的目标Q如清单 4 所C:


清单 4. 创徏 FindBugs 目录
1  <target name="FindBugs" depends="compile">
2 <FindBugs home="${FindBugs.home}" output="xml" outputFile="jedit-output.xml">
3 <class location="c:\apps\JEdit4.1\jedit.jar" />
4 <auxClasspath path="${basedir}/lib/Regex.jar" />
5 <sourcePath path="c:\tempcbg\jedit" />
6 </FindBugs>
7 </target>

让我们更详细地分析这D代码中所发生的过E?/p>

W?1 行: 注意 target 取决于编译。一定要C处理的是cL件? ?/em> 是源文gQ这样 target 对应于编译目标保证了 FindBugs 可在最新的cL件运行。FindBugs 可以灉|地接受多U输入,包括一l类文g、JAR 文g、或者一l目录?

W?2 行:必须指定包含 FindBugs 的目录,我是?Ant 的一个属性完成的Q像q样Q?

<property name="FindBugs.home" value="C:\apps\FindBugs-0.7.3" />

可选属? output 指定 FindBugs 的结果用的输出格式。可能的值有 xml ? text 或? emacs 。如果没有指? outputFile Q那?FindBugs 会用标准输出。如前所qͼXML 格式有可以在 UI 中观看的额外好处?

W?3 行: class 元素用于指定?FindBugs 分析哪些 JAR、类文g或者目录。分析多?JAR 或者类文gӞ要ؓ每一个文件指定一个单独的 class 元素。除非加入了 projectFile 元素Q否则需? class 元素。更多细节请参阅 FindBugs 手册?

W?4 行: 用嵌套元? auxClasspath 列出应用E序的依赖性。这些是应用E序需要但是不希望 FindBugs 分析的类。如果没有列出应用程序的依赖关系Q那?FindBugs 仍然会尽可能地分析类Q但是在找不C个缺的cLQ它会抱怨。与 class 元素一P可以?FindBugs 元素中指定多? auxClasspath 元素? auxClasspath 元素是可选的?

W?5 行: 如果指定? sourcePath 元素Q那? path 属性应当表明一个包含应用程序源代码的目录。指定目录 FindBugs 可以?GUI 中查?XML l果时突出显C出错的源代码。这个元素是可选的?

上面是基本内容了。让我们提前几个星期?

qo?/span>

(zhn)? 已经?FindBugs 引入C团队中,q运行它作ؓ(zhn)的每小?每晚~译q程的一部分。当团队来熟(zhn)这个工hQ出于某些原因,(zhn)决定所到的一些缺陷对于团队来说不? 要。也许?zhn)不关心一些类是否q回可能被恶意修改的对象——也许,? JEditQ有一个真正需要的Qhonest-to-goodnessQ、合法的理由调用 System.gc() ?

L可以选择“关闭”特定? 器。在更细化的水^上,可以在指定的一l类甚至是方法中查找问题Ӟ排除某些器。FindBugs 提供了这U细化的控制Q可以排除或者包含过滤器。当前只有用命o行或?Ant 启动?FindBugs 中支持排除和包含qo器。正如其名字所表明的,使用排除qo器来排除Ҏ(gu)些缺L报告。较为少见但仍然有用的是Q包含过滤器只能用于报告指定的缺陗过? 器是在一?XML 文g中定义的。可以在命o行中用一个排除或者包含开兟뀁或者在 Ant ~译文g中用 excludeFilter ? includeFilter 指定它们。在下面的例子中Q假定用排除开兟뀂还要注意在下面的讨ZQ我?“bugcode”?#8220;bug” ?#8220;detector”的用具有某U程度的互换性?

可以有不同的方式定义qo器:

  • 匚w一个类的过滤器。可以用q些qo?忽略在特定类中发现的所有问题?

  • 匚w一个类中特定缺陷代码(bugcodeQ的 qo器。可以用q些qo器忽略在特定cM发现的一些缺陗?

  • 匚w一l缺Lqo器。可以用q些qo?忽略所分析的所有类中的一l缺陗?

  • 匚w所分析的一个类中的某些Ҏ(gu)的过滤器。可以用q些qo器忽略在一个类中的一l方法中发现的所有缺陗?

  • 匚w在所分析的一个类中的Ҏ(gu)中发现的某些~陷的过滤器。可以用q些qo器忽略在一l方法中发现的特定缺陗?/li>

知道了这些就可以开始用了。有兛_他定?FindBugs Ҏ(gu)的更多信息,请参?FindBugs 文档。知道如何设|编译文件以后,p我们更详l地分析如何?FindBugs 集成到编译过E中吧!





回页?/strong>


?FindBugs 集成到编译过E中

在将 FindBugs 集成到编译过E当中可以有几种选择。L可以在命令行执行 FindBugsQ但是?zhn)很可能已l?Ant q行~译Q所以最自然的方法是使用 FindBugs Ant d。因为我们在 如何q行 FindBugs一节中讨论了?FindBugs Ant d的基本内容,所以现在讨论应当将 FindBugs 加入到编译过E中的几个理由,q讨论几个可能遇到的问题?

Z么应该将 FindBugs 集成到编译过E中Q?/span>

l? 帔R到的W一个问题是Z么要?FindBugs 加入到编译过E中Q虽然有大量理由Q最明显的回{是要保证尽可能早地在进行编译时发现问题。当团队扩大Qƈ且不可避免地在项目中加入更多新开发h? ӞFindBugs 可以作ؓ一个安全网Q检出已经识别的缺h式。我想重甛_一?FindBugs 论文中表q的一些观炏V如果让一定数量的开发h员共同工作,那么在代码中׃出现~陷。像 FindBugs q样的工具当然不会找出所有的~陷Q但是它们会帮助扑և其中的部分。现在找出部分比客户在以后找到它们要好——特别是当将 FindBugs l合到编译过E中的成本是如此低时?/p>

一旦确定了加入哪些qo器和c,q行 FindBugs 没什么成本了Q而带来的好处是它会出新缺陗如果编写特定于应用E序的检器Q则q个好处可能更大?/p>

生成有意义的l果

? 要的是要认识到这U成?效益分析只有在不生成大量误检时才有效。换句话_如果在每ơ编译时Q不能简单地定是否引入了新的缺P那么q个工具的h(hun)值就 会被抉|。分析越自动化越好。如果修复缺h味着必须吃力地分析检出的大量不相干的缺P那么(zhn)就不会l常使用它,或者至不会很好地使用它?/p>

定不关心哪些问题ƈ从编译中排除它们。也可以挑出 x的一部分检器q只q行它们。另一U选择是从个别的类中排除一l检器Q但是其他的cM排除。FindBugs 提供了用过滤器的极大灵zL,q可帮助生成对团队有意义的结果,由此我们q入下一节?

定?FindBugs 的结果做什?/span>

? 能看来很昄Q但是?zhn)想不到我参与的团队中有多加入了cM FindBugs q样的工兯没有真正利用它。让我们更深入地探讨q个问题——用l果做什么?明确回答q个问题是困隄Q因与团队的l织方式、如何处理代码所有权问题 {有很大关系。不q,下面是一些指|





回页?/strong>


l束?/span>

? 鼓励读者对自己的代码试用静态分析工P不管?FindBugs、PMD q是其他的。它们是有用的工P可以扑և真正的问题,?FindBugs 是在消除误检斚w做得最好的工具。此外,它的可插入结构提供了~写有h(hun)值的、特定于应用E序的检器的、有意思的试框架。在本系列的 W?2 部分中,我将展示如何~写自定义检器以找出特定于应用E序的问题?



参考资?



关于作?/span>


Chris Grindstaff 是在北加利福g Research Triangle Park 工作?IBM 高软g工程师。Chris ?7 岁时~写了他的第一个程序,当时他让学老师认识?#8220;键入”句子与手写它们一栯力。Chris 目前参与了不同的开放源代码目。他大量使用 Eclipse q编写了几个行?Eclipse 插gE序Q可以在他的 |站扑ֈq些插gE序。可以通过 cgrinds@us.ibm.com或? chris@gstaff.org?Chrise 联系?






二胡 2009-04-16 13:12 发表评论
]]> վ֩ģ壺 | | üɽ| ˫| ֱ| ̨| | | | | »| ׯ| տ| | | | | Ρɽ| ݳ| | ޼| Ͻ| Դ| ƽ| ϲ| ƽ½| ݸ| | | | | ͼʲ| ¹| | ͼ| ˷| | | ׯ| | |