posts - 11, comments - 10, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

静态分析工具及使用总结(一)

Posted on 2006-11-09 17:21 繁星满空 阅读(3154) 评论(0)  编辑  收藏 所属分类: Java

这里主要介绍三种开源的工具,PMDCheckStyleFindBugs,着重是在Ant里的调用,据说商业软件JTest也是著名的代码分析工具,哈哈,要花钱的没有用过。

 

PMD http://pmd.sourceforge.net/

简介: PMD 扫描java源代码,查找潜在的问题,如:

可能的bugs,如空的try/catch/finally/switch声明

死亡的代码,没有使用的本地变量,参数和私有方法

不合标准的代码,如String/StringBuffer用法

过于复杂的表达式,如不必要的if表达式

重复的代码,拷贝、粘贴的代码

PMD 的含义,如

Project Mess Detector

Project Monitoring Directives

Project Meets Deadline

Programming Mistake Detector…

 

用法: 可以在命令行下执行,如

pmd c:\Test.java xml rulesets/unusedcode.xml

也可以使用IDE的插件,如EclipseIDEAJBuilderJCreator等等

这里主要介绍Ant里的调用,

下面是主要的Ant配置信息
<path id="pmd.path">    
    
<fileset dir="${lib.dir}/pmd-3.8">
        
<include name="**/*.jar" />
    
</fileset>
</path>
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask" classpathref="pmd.path"/>
<taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask" classpathref="pmd.path"/>
    
<target name="pmd">
        
<pmd shortFilenames="true">
            
<ruleset>rulesets/favorites.xml</ruleset>            
            
<formatter type="html" toFile="d:\foo.html" toConsole="false"/>
            
<fileset dir="${src.dir}">
                
<include name="**/*.java"/>
            
</fileset>
        
</pmd>
    
</target>
<target name="cpd">        
        
<cpd minimumTokenCount="100" outputFile="d:/cpd.txt">
            
<fileset dir="${src.dir}">
                
<include name="**/*.java"/>
            
</fileset>
        
</cpd>
    
</target>

自定义规则:

有两个办法来自定义规则,可以编写java类和编写XPath,编写java类的一般步骤是,先确定要查找的代码形式,利用PMD自带的designer.bat工具查看AST(抽象语法树),然后编写规则类(继承net.sourceforge.pmd.AbstractRule),然后编写一个rulesetXML文件,最后就可以运行PMD进行检查。编写XPath比编写java类要容易些,但也需要掌握AST的含义,利用designer.bat工具可以查看AST,比如 //ClassBody [count(//VariableDeclarator[../Type/Name[@Image='Logger']])>1] ,这个表达式就是查找类的代码里是否声明了多个 Logger ,然后编写一个 ruleset XML 文件,最后运行 PMD 进行检查。这里是一个 ruleset XML 文件的例子。

 

自定义规则集合:

PMD 自带了很多代码规范的规则,还可以自定义规则,我们可以把这些规则整合到一起,按照我们的需求进行代码检查。
<!-- 使用整个strings规则集 -->
  
<rule ref="rulesets/strings.xml"/>
<!-- 使用某个规则集里的某个规则 -->
  
<rule ref="rulesets/unusedcode.xml/UnusedLocalVariable"/>
  
<!-- 指定某个规则集里的某个规则的优先级 -->
<rule ref="rulesets/basic.xml/EmptyCatchBlock" message="Must handle exceptions">
    
<priority>2</priority>
    
</rule>
          
<!-- 去除某个规则集里的某个规则 -->
<rule ref="rulesets/braces.xml">
    
<exclude name="WhileLoopsMustUseBracesRule"/>
  
</rule>

最后,我们运行PMD的时候就可以指定这个 ruleset 文件。

 

自带规则的介绍:

PMD 自带了很多规则集合,并且分类写入不同的 ruleset 文件,如

Basic 包含每人都必须遵守的代码最佳实践,如EmptyCatchBlock

Braces 关于条件分支的规则,如IfStmtsMustUseBraces

Code Size 关于代码大小的规则,如方法的长度,参数的长度,属性的个数等

Clone 克隆实现的规则,如是否有super.clone()

Controversial 一些有争议的规则,如UnnecessaryConstructor不必要的构造器

Coupling 对象连接有关的规则

Design 可以检查有问题的设计,如SwitchStmtsShouldHaveDefault

Finalizers 使用finalizers时需遵循的规则,如FinalizeOnlyCallsSuperFinalize

Import Statements import有关的规则,如DuplicateImports重复import

J2EE 唯一规则UseProperClassLoaderclass.getClassLoader()可能不正确,用

Thread.currentThread().getContextClassLoader() 代替

Javabeans javabean规范有关的规则,有BeanMembersShouldSerialize属性必须

序列化和MissingSerialVersionUID缺少序列化ID

JUnit Tests JUnit测试有关的,如JUnitSpelling拼写检查等

Logging (Java) 检查Logger的一些错误用法,如MoreThanOneLogger多个Logger

Logging (Jakarta) 使用Jakarta Logger的一些规则,有UseCorrectExceptionLogging

异常处理不当和ProperLogger是否正确定义Logger

Migrating JDK 版本移植的规则,如ReplaceVectorWithListList代替Vector

Naming 和命名有关的规则,名称太短或太长,命名的约定等

Optimizations 优化性能的一些规则,如LocalVariableCouldBeFinal本地变量如果

只赋值一次,则应该声明为final

Strict Exceptions 比较严格的异常处理方针,如AvoidCatchingThrowable

Strings 使用StringStringBuffer时应遵守的规则,如StringToString

Sun Security 编写安全的代码,有MethodReturnsInternalArray直接返回内部的数组,

更安全的做法是返回一个拷贝和ArrayIsStoredDirectly

Unused Code 检查未使用的代码,如UnusedPrivateField未使用的私有属性

Java Server Pages 编写jsp的一些方针,如NoLongScripts

Java Server Faces 编写jsf的一些方针,有DontNestJsfInJstlIteration,在Jsf

里使用jstl的标签

PMD 里面还有一个写好的ruleset文件,在pmd-3.8.jar里面的rulesets文件夹下,名称是favorites.xml,以下是主要部分:

< rule  ref ="rulesets/basic.xml" />
< rule  ref ="rulesets/basic.xml/EmptyCatchBlock"  message ="Must handle exceptions" >
        
< priority > 2 </ priority >
</ rule >
    
< rule  ref ="rulesets/unusedcode.xml" />
< rule  ref ="rulesets/braces.xml/WhileLoopsMustUseBraces" />
< rule  ref ="rulesets/braces.xml/ForLoopsMustUseBraces" />
< rule  ref ="rulesets/design.xml/SimplifyBooleanReturns" />
< rule  ref ="rulesets/design.xml/SwitchStmtsShouldHaveDefault" />
< rule  ref ="rulesets/strings.xml/StringToString" />
< rule  ref ="rulesets/strings.xml/StringInstantiation" />
< rule  ref ="rulesets/controversial.xml/UnnecessaryConstructor" />
< rule  ref ="rulesets/controversial.xml/NullAssignment" />
< rule  ref ="rulesets/controversial.xml/UnusedModifier" />
< rule  ref ="rulesets/codesize.xml/CyclomaticComplexity" >
    
< properties >< property  name ="reportLevel"  value ="5" /></ properties >
</ rule >

其它事项:

1.     可以使用JDK1.5的声明 @SuppressWarnings(""),禁止PMD的警告。

2.     可以使用//NOPMD来标记行或块代码,禁止PMD警告。

3.     有两种方法自定义Rule,编写java类和编写XPath

4.     PMD 提供了多种IDE的插件来运行PMD

 

 

 

参考文档:

PMD 官方文档(http://pmd.sourceforge.net/

OnJava 上一篇文档( http://www.onjava.com/pub/a/onjava/2003/04/09/pmd_rules.html

代码静态分析(http://blog.donews.com/foxgem/archive/2005/04/23/347444.aspx

 


只有注册用户登录后才能发表评论。


网站导航: