上一节使用checkstyle来规范你的项目主要解决了代码编码规范问题,比如缩进换行等。这次继续代码健康工具类PMD。

什么是PMD

PMD真的不像checkstyle这样的东西所见即所得啊,去官网找了半天也没有找到解释。官网都直接说是PMD。

We've been trying to find the meaning of the letters PMD - because frankly, we don't really know. We just think the letters sound good together.

简单来说,PMD是一个代号,是一个静态代码检测工具。它可以用来检查

  • 潜在的bug:空的try/catch/finally/switch语句
  • 未使用的代码:未使用的局部变量、参数、私有方法等
  • 可选的代码:String/StringBuffer的滥用
  • 复杂的表达式:不必须的if语句、可以使用while循环完成的for循环
  • 重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs

总之,这是一个辅助我们检测潜在bug的工具,大大减少了人工审查成本,提高编码效率。

在gradle中使用

gradle还是一贯的简单,新建pmd.gradle

/**
* The PMD Plugin
*
* Gradle plugin that performs quality checks on your project’s Java source files using PMD
* and generates reports from these checks.
*
* Tasks:
* Run PMD against {rootDir}/src/main/java: ./gradlew pmdMain
* Run PMD against {rootDir}/src/test/java: ./gradlew pmdTest
*
* Reports:
* PMD reports can be found in {project.buildDir}/build/reports/pmd
*
* Configuration:
* PMD is very configurable. The configuration file is located at {rootDir}/config/pmd/pmd-ruleset.xml
*
* Additional Documentation:
* https://docs.gradle.org/current/userguide/pmd_plugin.html
*/ apply plugin: 'pmd' pmd {
// The version of the code quality tool to be used.
// The most recent version of PMD can be found at https://pmd.github.io
toolVersion = "5.8.1" // The source sets to be analyzed as part of the check and build tasks.
// Use 'sourceSets = []' to remove PMD from the check and build tasks.
sourceSets = [project.sourceSets.main] // The directory where reports will be generated.
reportsDir = file("$project.buildDir/reports/pmd") // Whether to allow the build to continue if there are warnings.
ignoreFailures = false // Whether or not rule violations are to be displayed on the console.
consoleOutput = true // The custom rule set files to be used.
ruleSetConfig = resources.text.fromFile("$rootProject.projectDir/config/pmd/pmd-ruleset.xml")
}

添加我们的pmd-ruleset.xml配置文件, 这个ruleset有很多种,我们可以先把所有的加上,然后在开发中调整,直到找到最合适的配置方案。因为全部的规则太多,会导致你花费大量的时间解决PMD问题。

ruleset内容可以在https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html 这里找到

然后在build.gradle中添加

apply from: 'pmd.gradle'

执行

./gradlew check  或者 ./gradlew build

报告位置:

build/reports/pmd/main.html

在maven中使用

maven需要把ruleset放到resources下读取,如果是单moudle项目,直接就可以。如果是多模块项目,需要额外做一些工作。

我们来新建一个项目来单独存储配置文件,build-tools. 在resources下放置ruleset。名字叫做pmd-ruleset.xml, 内容见https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html

然后maven install把这个子模块给安装到本地仓库。

接着修改parent pom

<build>

    <pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.10.0</version>
<dependencies>
<dependency>
<groupId>com.shuwei</groupId>
<artifactId>build-tools</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
<configuration>
<sourceEncoding>utf-8</sourceEncoding>
<minimumTokens>100</minimumTokens>
<targetJdk>${java.version}</targetJdk>
<excludes>
<exclude>**/message/*.java</exclude>
<exclude>**/generated/*.java</exclude>
</excludes>
<excludeRoots>
<excludeRoot>target/generated-sources</excludeRoot>
</excludeRoots>
<rulesets>
<ruleset>pmd-ruleset.xml</ruleset>
</rulesets>
<printFailingErrors>true</printFailingErrors>
</configuration>
<executions>
<execution>
<id>install</id>
<phase>install</phase>
<goals>
<goal>pmd</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement> <!--所有子模块都要执行的plugin-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
</plugin>
</plugins> </build> <reporting>
<!--所有子模块都要执行的报告-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
</plugin>
</plugins>
</reporting>

和上一节checkstyle不同的时候,这里的plugin下新增了dependency节点。这个节点负责加载一些资源过来,比如我们的配置文件ruleset。所以,这个dependency要先于项目存在,所以才要先单独install一下。当然,也可以把这个项目放到maven私服上,这样更简单了。

依旧把pmd的运行绑定到install命令上,这样,我们运行maven install的时候就可以进行pmd检查了。

检查报告在

j-context/target/site/pmd.html

也可以单独运行pmd

mvn pmd:pmd

idea插件

搜索安装idea pmd插件,导入我们的ruleset, 然后在项目上右键,run pmd即可。

Ruleset default内容

可以在maven官网看到: https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html

PMD 包含 16 个规则集,涵盖了 Java 的各种常见问题,其中一些规则要比其他规则更有争议:

基本(rulesets/basic.xml)—— 规则的一个基本合集,可能大多数开发人员都不认同它: catch 块不该为空,无论何时重写 equals(),都要重写 hashCode(),等等。

命名(rulesets/naming.xml)—— 对标准 Java 命令规范的测试:变量名称不应太短;方法名称不应过长;类名称应当以小写字母开头;方法和字段名应当以小写字母开头,等等。

未使用的代码(rulesets/unusedcode.xml)—— 查找从未使用的私有字段和本地变量、执行不到的语句、从未调用的私有方法,等等。

设计(rulesets/design.xml)—— 检查各种设计良好的原则,例如: switch 语句应当有 default 块,应当避免深度嵌套的 if 块,不应当给参数重新赋值,不应该对 double 值进行相等比较。

导入语句(rulesets/imports.xml)—— 检查 import 语句的问题,比如同一个类被导入两次或者被导入 java.lang 的类中。

JUnit 测试(rulesets/junit.xml)—— 查找测试用例和测试方法的特定问题,例如方法名称的正确拼写,以及 suite() 方法是不是 static 和 public。

字符串(rulesets/string.xml)—— 找出处理字符串时遇到的常见问题,例如重复的字符串标量,调用 String 构造函数,对 String 变量调用 toString() 方法。

括号(rulesets/braces.xml)—— 检查 for、 if、 while 和 else 语句是否使用了括号。

代码尺寸(rulesets/codesize.xml)—— 测试过长的方法、有太多方法的类以及重构方面的类似问题。

Javabean(rulesets/javabeans.xml)—— 查看 JavaBean 组件是否违反 JavaBean 编码规范,比如没有序列化的 bean 类。

终结函数(finalizer)—— 因为在 Java 语言中, finalize() 方法不是那么普遍(我上次编写这个代码也经是好多年前的事了),所以它们的使用规则虽然很详细,但是人们对它们相对不是很熟悉。这类检查查找 finalize() 方法的各种问题,例如空的终结函数,调用其他方法的 finalize() 方法,对 finalize() 的显式调用,等等。

克隆(rulesets/clone.xml)—— 用于 clone() 方法的新规则。凡是重写 clone() 方法的类都必须实现 Cloneable, clone() 方法应该调用 super.clone(),而 clone() 方法应该声明抛出 CloneNotSupportedException 异常,即使实际上没有抛出异常,也要如此。

耦合(rulesets/coupling.xml)—— 查找类之间过度耦合的迹象,比如导入内容太多;在超类型或接口就已经够用的时候使用子类的类型;类中的字段、变量和返回类型过多等。

严格的异常(rulesets/strictexception.xml)—— 针对异常的测试:不应该声明该方法而抛出 java.lang.Exception 异常,不应当将异常用于流控制,不应该捕获 Throwable,等等。

有争议的(rulesets/controversial.xml)—— PMD 的有些规则是有能力的 Java 程序员可以接受的。但还是有一些争议。这个规则集包含一些更有问题的检验,其中包括把 null 赋值给变量、方法中有多个返回点,以及从 sun 包导入等。

日志(rulesets/logging-java.xml)—— 查找 java.util.logging.Logger 的不当使用,包括非终状态(nonfinal)、非静态的记录器,以及在一个类中有多个记录器。

参考

添加PMD插件扫描潜在的bug的更多相关文章

  1. IDEAL葵花宝典:java代码开发规范插件 checkstyle、visualVM、PMD 插件

    前言: visualVM: 运行java程序的时候启动visualvm,方便查看jvm的情况 比如堆内存大小的分配:某个对象占用了多大的内存,jvm调优必备工具. checkstyle: CheckS ...

  2. Gradle 1.12用户指南翻译——第三十三章. PMD 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  3. Ubuntu 14.04安装Chromium浏览器并添加Flash插件Pepper Flas

    转自Ubuntu 14.04安装Chromium浏览器并添加Flash插件Pepper Flash Player Chromium谷歌的开源浏览器将不再支持Netscape浏览器插件API,Adobe ...

  4. Emacs添加主题插件(Win系统)

    Emacs添加主题插件(Win系统) */--> /* @licstart The following is the entire license notice for the JavaScri ...

  5. SSM整合中遇到的不能扫描注解的bug

    我的开发环境为: ubuntu14.04LTS 64bit; Spring Tool Suite  3.5.0.RELEASE Maven 3.2.3 SSM整合中遇到的不能扫描注解的bug 最终解决 ...

  6. IntelliJ IDEA 添加junit插件

    一.使用idea做junit测试需要添加junit插件 1.安装插件 File-->settings-->Plguins-->Browse repositories-->输入J ...

  7. eclipse手动安装alibaba代码规范插件+取消阿里编码规约插件扫描出来的警告及错误

    如果你的开发环境无法访问外网,那么手动安装阿里巴巴的代码规范插件是一个不错的选择.另外,很多教程说该插件需要jdk1.8以上,我试了一下jdk1.7也是可以运行的,更低的版本就不知道了,貌似jdk1. ...

  8. WordPress插件扫描工具plecost

    WordPress插件扫描工具plecost   WordPress是PHP语言开发的博客平台.该平台允许用户通过插件方式扩展博客功能.由于部分插件存在漏洞,给整个网站带来安全风险.Kali Linu ...

  9. atitit.MyEclipse10 中添加svn插件故障排除

    atitit.MyEclipse10 中添加svn插件故障排除 删除\configuration \org.eclipse.update 不行... 二. 在configuration下的config ...

随机推荐

  1. SQL Server Management Studio 教程二: 创建新登录名

    1.先用windows身份登录SQL server2008 2.打开[安全性],右击[登录名],选择[新建登录名] 3.[常规]选项页面中,修改如下位置设置,默认数据库可以是其他数据库,不一定是mas ...

  2. 【Hadoop】HDFS - 创建文件流程详解

    1.本文目的 通过解析客户端创建文件流程,认知hadoop的HDFS系统的一些功能和概念. 2.主要概念 2.1 NameNode(NN): HDFS系统核心组件,负责分布式文件系统的名字空间管理.I ...

  3. tesseract-ocr识别中文扫描图片实例讲解

    当我浏览http://code.google.com/p/tesseract-ocr并下载了几个文件下来之后顿时感到一头雾水,不知该如何下手.网上看到有人在linux操作系统下的实现, 如: 利用开源 ...

  4. Dell PowerEdge R710服务器内存条插法/Dell 11G/12G系列服务器内存条插法(转)

    说明:以我的经验,其实插3/6/9这个顺序去一定没有错. DELL PowerEdge R710服务器支持 DDR3的 DIMM (RDIMM) 或 ECC非缓冲的 DIMM(UDIMM).单列和双列 ...

  5. [Winform]检测exe是否已经运行,并将其置顶

    摘要 在很多pc应用中,基本上都需要有这样的判断,保证在一个终端只运行一个winform的client.并且如果最小化了,用户再次双击桌面图标的时候,将client置顶显示. 解决方案 需要使用win ...

  6. DNS服务器

    DNS服务器是指“域名解析服务器”,而域名就是我们通常所说的“网址”.在互联网中识别和寻找不同的计算机,实际上是需要知道该计算机的IP地址才能进行访问.比如220.181.38.4,这个IP就是百度的 ...

  7. 【iOS开发-91】GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例

    (1)GCD实现的同步异步.串行并行. --同步sync应用场景:用户登录,利用堵塞 --串行异步应用场景:下载等耗时间的任务 /** * 由于是异步.所以开通了子线程.可是由于是串行队列,所以仅仅须 ...

  8. NSArray进行汉字排序

    由于NSArray并不直接支持对汉字的排序,这就要通过将汉字转换成拼音完毕按A~Z的排序,这看起来是个头疼的问题.由于牵扯到汉字转为拼音,kmyhy给出一个较易实现的方法,获取汉字的首字的首字母,如将 ...

  9. Windows XP UDF 2.5 补丁,播放蓝光ISO光盘必备

    蓝光光盘的文件系统是UDF2.5,Windows XP及以下的操作系统默认不能支持这个文件系统.当我们在XP系统中使用蓝光光盘或蓝光ISO文件时,就会提示“Windows不能从此盘读取,此盘可能已损坏 ...

  10. 设置Images.xcassets后启动仍旧黑屏的问题

    换了XCode6之后,发现以前写Icon-76.png这样很麻烦,就使用了Image.xcassets,公司所有测试机跑了一下,发现没什么问题.唯独有一台设置有问题,iphone5 ios6.0系统, ...