1. 程式人生 > >靜態分析工具PMD使用總結

靜態分析工具PMD使用總結

簡介: 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的外掛,如Eclipse、IDEA、JBuilder、JCreator等等

這裡主要介紹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),然後編寫一個ruleset的XML檔案,最後就可以執行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 唯一規則UseProperClassLoader,class.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 版本移植的規則,如ReplaceVectorWithList用List代替Vector

Naming 和命名有關的規則,名稱太短或太長,命名的約定等

Optimizations 優化效能的一些規則,如LocalVariableCouldBeFinal本地變數如果

只賦值一次,則應該宣告為final

Strict Exceptions 比較嚴格的異常處理方針,如AvoidCatchingThrowable

Strings 使用String和StringBuffer時應遵守的規則,如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。

參考文件:

程式碼靜態分析(http://blog.donews.com/foxgem/archive/2005/04/23/347444.aspx)