全面剖析PMD靜態程式碼掃描工具
這是個人原創的一篇全面介紹PMD靜態程式碼掃描工具的文件,最近部門需要調研靜態程式碼掃描工具以提高程式碼的質量,經過對比幾十款工具,剔除了商用和多年沒有更新的,最終鎖定的有PMD、SanorQube以及Facebook infer。
PMD是使用JavaCC
生成解析器來解析原始碼並生成AST(抽象語法樹)的,這兩天對PMD及自定義規則做了調研及實驗,部分說明來自官方說明文件,做了大部分引數的詳細描述及測試,少數幾個引數不明白含義,有了解的朋友歡迎討論。
1 調研物件
pmd-bin-6.4.0【PMD可執行版本】
· bin
· designer.bat【介面工具,能將java
· bgastviewer.bat【介面工具,與designer.bat功能相似】
· cpd.bat【用來查詢重複程式碼的工具,命令列版】
· cpdgui.bat【用來查詢重複程式碼的工具,GUI版】
· pmd.bat【Window平臺下執行PMD需要使用的檔案】
· run.sh【Linux平臺下執行PMD需要使用的檔案】
· lib【該目錄存放PMD執行依賴的jar包,包括第三方jar包和各種語言的模組jar包】
2 基本使用
格式:pmd -d [filename|jar or zip file containing source code|directory]-f [report format] -R [ruleset file]
示例:E:\pmd-bin-6.4.0>bin\pmd.bat -d E:\name -f html -R java-basic,java-design
如果要將生成的結果儲存出來可以使用命令列重定向儲存到指定路徑——
E:\pmd-bin-6.4.0>bin\pmd.bat -d E:\name -f html -R java-basic,java-design>report.html
Option | Description | Required | Applies for language |
-rulesets / -R | Comma separated list of ruleset names to use | yes | |
-dir / -d | Root directory for sources | yes | |
-format / -f | Report format type. Default format is `text`. | no | |
-auxclasspath | Specifies the classpath for libraries used by the source code. This is used by the type resolution. Alternatively a `file://` URL to a text file containing path elements on consecutive lines can be specified. | no | |
-uri / -u | Database URI for sources. If this is given, then you don't need to provide `-dir`. | no | plsql |
-filelist | Path to file containing a comma delimited list of files to analyze. If this is given, then you don't need to provide `-dir`. | no | |
-debug / -verbose / -D / -V | Debug mode. Prints more log output. | no | |
-help / -h / -H | Display help on usage. | no | |
-encoding / -e | Specifies the character set encoding of the source code files PMD is reading (i.e. UTF-8). Default is `UTF-8`. | no | |
-threads / -t | Sets the number of threads used by PMD. Default is `1`. Set threads to '0' to disable multi-threading processing. | no | |
-benchmark / -b | Benchmark mode - output a benchmark report upon completion; defaults to System.err | no | |
-stress / -S | Performs a stress test. | no | |
-shortnames | Prints shortened filenames in the report. | no | |
-showsuppressed | Report should show suppressed rule violations. | no | |
-suppressmarker | Specifies the string that marks the line which PMD should ignore; default is `NOPMD`. | no | |
-minimumpriority / -min | Rule priority threshold; rules with lower priority than configured here won't be used. Default is `5` - which is the lowest priority. | no | |
-property / -P | `{name}={value}`: Define a property for a report format. | no | |
-reportfile / -r | Send report output to a file; default to System.out | no | |
-version / -v | Specify version of a language PMD should use. | no | |
-language / -l | Specify a language PMD should use. | no | |
-failOnViolation {true|false} | By default PMD exits with status 4 if violations are found. Disable this option with '-failOnViolation false' to exit with 0 instead and just write the report. | no | |
-cache | Specify a location for the analysis cache file to use. This can greatly improve analysis performance and is highly recommended. | no | |
-no-cache | Explicitly disable incremental analysis. This switch turns off suggestions to use Incremental Analysis, and causes the -cacheoption to be discarded if it is provided. |
2 規則
2.1規則集
RuleCategories
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 和命名有關的規則,名稱太短或太長,命名的約定等
2.2引數詳情
● -dir/-d掃描目錄
● -format/-f報告格式,有xml、xslt、html、text,預設為text
● -rulesets/R使用的規則集
● -auxclasspath
● -uri/-u原始檔的資料庫uri,使用它就不需要提供-dir
● -filelist一個包含逗號分隔的路徑列表的檔案,使用它就不需要提供-dir
示例:
命令:E:\pmd-bin-6.4.0>bin\pmd.bat -filelist E:\team-goblin\demo1\list.txt -f html -R myRule.xml
結果:
● -debug / -verbose / -D / -V 列印更詳細的日誌
● –help 顯示用法幫助資訊
● -encoding / -e 字符集編碼,預設為utf-8
● -threads / -t 設定PMD使用的執行緒數。預設值是“1”。將執行緒設定為“0”以禁用多執行緒處理。
● -benchmark / -b 基準模式-完成後輸出基準測試報告
● -stress / -S 進行壓力測試
● –shortnames 報告中列印縮短的檔名,只有在檔案只有一個目錄時是奏效
示例:
使用 –shortnames後:
● –suppressmarker 指定一個字串使得PMD忽略某行,預設為“NOPMD”。
示例1:
示例2:pmd.bat -d E:\team-goblin\demo1 -f html -RmyRule.xml -showsuppressed -suppressmarker allowint
● – showsuppressesd 報告顯示被忽略的違規行為
示例:bin\pmd.bat -d E:\team-goblin\demo1 -f html –R myRule.xml-showsuppressesd>report.html
● –minimumpriority/-min
規則最小優先順序閾值,預設為5,規則優先順序低於它就不會被使用
示例:
pmd.bat-d E:\team-goblin\demo1 -f html -R myRule.xml -min 4
● –property/-P 為報告格式定義一個屬性
● –language/-l 指定pmd使用的語言
【對掃描結果沒有任何影響】
● - version 指定PMD使用的語言版本
● – failOnViolation {true|false} PMD預設會在發現違規情況時以狀態4退出。使用“-failOnViolation false”禁用此選項,以0退出並且只寫報告。
0 | Everything is fine, no violations found |
1 | Couldn't understand command line parameters or PMD exited with an exception |
4 | At least one violation has been detected |
● -cache指定要使用的分析快取檔案的位置。這可以大大提高分析效能,並被強烈推薦。
● –no-cache顯式禁用增量分析。這個開關關閉了使用增量分析的建議,並導致-cache選項使用時無效
2.3 自定義規則
編寫pmd規則有兩種方法:
(1)用xpath,參考產生的AST樹寫xml
(2)用java code,需要深入瞭解pmd api,用於一些比較複雜的規則
2.3.1xpath自定義規則
使用PMD自帶的designer.bat工具可以快速生成一個xpath rule xml。(1)開啟designer介面工具,輸入原始碼,輸入XPath表示式,點選Go按鈕,確認右下方的結果輸出正確。
(2)點選左上方File->ExportXpath to rule
(3)在新的頁面輸入Rulename,Rule msg,Rule desc後,點選Create rule XML按鈕,檢視輸出的結果。
示例:
判斷非Integer的引用型別//Type/ReferenceType/ClassOrInterfaceType[@Image!="Integer"]
判斷使用Int的基本型別
//Type/PrimitiveType[@Image="int"]
3 擴充套件
3.1 cpd.bat 重複程式碼檢測
cpd.bat --minimum-tokens 100 --filesE:\team-goblin
--minimum-tokens 大於該值則認為程式碼重複
--files 掃描檔案路徑
SupportedLanguages
- Apex
- C#
- C/C++
- EcmaScript (JavaScript)
- Fortran
- Go
- Groovy
- Java
- Jsp
- Matlab
- Objective-C
- Perl
- PHP
- PL/SQL
- Python
- Ruby
- Scala
- Swift
- Visualforce
Availableformats
- text : Default format
- xml
- csv
- csv_with_linecount_per_file
- vs
參考資料:
360Test部落格:點選開啟連結