pmd静态源码分析⼯具简介及配置
在正式进⼊测试之前,进⾏⼀定的静态代码分析及code review对代码质量及系统提⾼是有帮助的,以上为数据证明
Pmd 它是⼀个基于静态规则集的Java源码分析器,它可以识别出潜在的如下问题:
– 可能的bug——空的try/catch/finally/switch块。
– ⽆⽤代码(Dead code):⽆⽤的本地变量,⽅法参数和私有⽅法。
– 空的if/while语句。
正式的反义词– 过度复杂的表达式——不必要的if语句,本来可以⽤while循环但是却⽤了for循环。
– 可优化的代码:浪费性能的String/StringBuffer的使⽤。
下载pmd ,配置CLASSPATH等内容
requirement
1.6 or higher
or the free
将压缩包解压在C盘
cmd 后然后输⼊以下内容:
-dir 指定⽬录, -f 指定⽣成的结果的格式 -R 使⽤何种规则进⾏检测
rulets/java/*.xml 具体地址在pmd-bin-5.4.2\bin
规则如下:
PMD 包含 16 个规则集,涵盖了 Java 的各种常见问题,其中⼀些规则要⽐其他规则更有争议:
基本(l)—— 规则的⼀个基本合集,可能⼤多数开发⼈员都不认同它:catch块不该为空,⽆论何时重写equals(),都要重写hashCode(),等等。
命名(l)—— 对标准 Java 命令规范的测试:变量名称不应太短;⽅法名称不应过长;类名称应当以⼩写字母开头;⽅法和字段名应当以⼩写字母开头,等等。
未使⽤的代码(l)—— 查找从未使⽤的私有字段和本地变量、执⾏不到的语
句、从未调⽤的私有⽅法,等等。
设计(l)—— 检查各种设计良好的原则,例如:switch语句应当有default块,应当避免深度嵌套的if块,不应当给参数重新赋值,不应该对 double 值进⾏相等⽐较。
二胡独奏葬花吟导⼊语句(l)—— 检查 import 语句的问题,⽐如同⼀个类被导⼊两次或者被导⼊java.lang的类中。
JUnit 测试(l)—— 查找测试⽤例和测试⽅法的特定问题,例如⽅法名称的正确拼写,以及suite()⽅法是不是 static 和 public。
字符串(l)—— 找出处理字符串时遇到的常见问题,例如重复的字符串标量,调⽤String构造函数,对String变量调⽤toString()⽅法。
括号(l)—— 检查for、if、while和el语句是否使⽤了括号。
代码尺⼨(l)—— 测试过长的⽅法、有太多⽅法的类以及重构⽅⾯的类似问题。
Javabean(l)—— 查看 JavaBean 组件是否违反 JavaBean 编码规范,⽐如没有序列化的 bean 类。
终结函数(finalizer)—— 因为在 Java 语⾔中,finalize()⽅法不是那么普遍(我上次编写这个代码也经是好多年前的事了),所以它们的使⽤规则虽然很详细,但是⼈们对它们相对不是很熟悉。这类检查查找finalize()⽅法的各种问题,例如空的终结函数,调⽤其他⽅法的finalize()⽅法,对finalize()的显式调⽤,等等。
克隆(l)—— ⽤于clone()⽅法的新规则。凡是重写clone()⽅法的类都必须实现Cloneable,clone()⽅法应该调
⽤super.clone(),⽽clone()⽅法应该声明抛出CloneNotSupportedException异常,即使实际上没有抛出异常,也要如此。
耦合(l)—— 查找类之间过度耦合的迹象,⽐如导⼊内容太多;在超类型或接⼝就已经够⽤的时候使⽤⼦类的类型;类中的字段、变量和返回类型过多等。
严格的异常(l)—— 针对异常的测试:不应该声明该⽅法⽽抛出java.lang.Exception异常,不应当将异常⽤于流控制,不应该捕获Throwable,等等。
有争议的(l)—— PMD 的有些规则是有能⼒的 Java 程序员可以接受的。但还是有⼀些争议。这个规则集包含⼀些更有问题的检验,其中包括把 null 赋值给变量、⽅法中有多个返回点,以及从sun包导⼊等。
⽇志(l)—— 查找java.util.logging.Logger的不当使⽤,包括⾮终状态(nonfinal)、⾮静态的记录器,以及在⼀个类中有多个记录器。
如果为了⼀次性将所需要的规则都进⾏检测,可以进⾏如下的操作
1、将现有的规则使⽤逗号进⾏隔离, rulets/l,rulets/l等
2、定义⾃⼰的规则集
<?xml version="1.0"?>
<rulet name="customrulet">
<description>
Sample rulet for developerWorks article
</description>
<rule ref="l"/>
<rule ref="l"/>
<rule ref="l"/>
</rulet>
更细致的规则集:
<?xml version="1.0"?>
<rulet name="specific rules">
<description>
Sample rulet for developerWorks article
</description>
<rule ref="l/AvoidReassigningParametersRule"/>
<rule ref=
"l/ConstructorCallsOverridableMethod"/>
<rule ref="l/FinalFieldCouldBeStatic"/>
<rule ref="l/DefaultLabelNotLastInSwitchStmt"/>
<rule ref="l/LongVariable"/>
<rule ref="l/ShortMethodName"/>
结构主义语言学
<rule ref="l/VariableNamingConventions"/>
<rule ref="l/MethodNamingConventions"/>
<rule ref="l/ClassNamingConventions"/>
<rule ref="l/EmptyCatchBlock"/>
<rule ref="l/EmptyFinallyBlock"/>
</rulet>
排除具体某个规则:
<?xml version="1.0"?>
<rulet name="dW rules">
<description>
Sample rulet for developerWorks article
才华</description>
<rule ref="l">
<exclude name="SwitchStmtsShouldHaveDefault"/>
</rule>
班田收授法
</rulet>
可以使⽤-r参数来讲检测的结果导出到某个地⽅
在线⽂档:
我们⾃⼰建⽴了⼀个⾃⼰的l⽂件,只是简单的包含⼀部分我们认为重要的规则.修改rulets.properties,并将l⽂件加⼊到压缩包中
facebank⾃⼰的规则如下;
<?xml version="1.0"?>
<rulet name="facebankrules">
<description>
Sample rulet for facebank developers
</description>
高中社团
<rule ref="rulets/l"/>
<rule ref="rulets/l"/>
<rule ref="rulets/l"/>
<rule ref="rulets/l"/>
南瓜营养
<rule ref="rulets/l"/>
<rule ref="rulets/l"/>
<rule ref="rulets/l"/>
<rule ref="rulets/l"/>
<rule ref="rulets/l"/>
<rule ref="rulets/l"/>
<rule ref="rulets/l"/>
机械能守恒条件</rulet>