PMD
相关工具推荐
| 工具 | 说明 |
|---|---|
| Checkstyle | Java 代码风格与规范检查工具,侧重命名、格式、Javadoc 等风格类检查 |
| SpotBugs | Java 字节码级缺陷检测工具,基于 Bug Patterns 发现潜在运行时问题 |
| Google-Java-Format | Google 出品的 Java 代码格式化工具,与 Google Java Style Guide 配合使用 |
| Spotless | 多语言代码格式化统一框架,支持 Maven/Gradle 集成 |
1. 简介
PMD 是一款开源的可扩展多语言静态代码分析工具,主要用于检测源代码中的潜在缺陷、不良编程实践和性能问题。PMD 通过 JavaCC 和 ANTLR 将源代码解析为抽象语法树(AST),然后对 AST 运行规则来发现违规。PMD 还内置了 CPD(Copy/Paste Detector)复制粘贴检测器,用于发现项目中的重复代码。
- 主要检查语言:Java(核心)、Apex、Kotlin、Swift、JavaScript、PLSQL、Go、Python 等
- 主要检查能力:检测未使用的变量、空 catch 块、不必要的对象创建、复杂代码等潜在问题;涵盖质量类检查(潜在缺陷、不良实践)、设计类检查(复杂度、耦合度)、安全类检查、性能类检查
- 核心检查原理:基于 AST 分析,支持 XPath 和 Java 自定义规则
- 检查规则/选项:规则按 Best Practices、Code Style、Design、Error Prone、Multithreading、Performance、Security 等 8 大类组织,数量随版本动态变化,Java 规则索引
- GitHub 仓库:https://github.com/pmd/pmd(5,422 stars)
- 开源协议:BSD-2-Clause
- 最新稳定版本:v7.11.0
- 运行环境要求:PMD 7.x 需 Java 8+ 运行;Gradle PMD 插件需 Gradle 8.6+,Maven PMD 插件需 maven-pmd-plugin 3.22.0+
- 误报率:中
2. 官方文档
3. 社区优秀实践
3.1 Apache Maven 项目
Apache Maven 自身在父 POM 中配置了 PMD 插件,对所有 Maven 子模块执行静态代码分析检查。Maven 是 Java 构建工具的事实标准,其 PMD 配置是社区中最具参考价值的实践之一。
- 仓库地址:https://github.com/apache/maven
- 配置特点:在
maven-parent中统一管理 PMD 插件版本和规则集配置,子模块通过继承自动应用 - 参考文件:
apache/maven/pom.xml中的maven-pmd-plugin配置
3.2 Alibaba P3C(阿里巴巴 Java 编码规范)
阿里巴巴基于 PMD 实现了 P3C(Java 编码规范)规则集,这是国内 Java 社区使用最广泛的 PMD 规则集之一。P3C 规则集涵盖了阿里巴巴《Java 开发手册》中的所有编码规范,包括命名规约、OOP 规约、集合处理、并发处理、控制语句、异常处理等。
- 仓库地址:https://github.com/alibaba/p3c
- 配置特点:提供了完整的 PMD 规则集实现和 IntelliJ IDEA / Eclipse 插件,支持 Maven 集成
- 规则集文件:
p3c-pmd/src/main/resources/rulesets/java/目录下包含所有规则定义
3.3 Spring Framework
Spring Framework 作为 Java 生态中最流行的应用框架之一,在其构建流程中集成了 PMD 进行代码质量检查。Spring 项目的 PMD 配置代表了大型企业级 Java 项目的最佳实践。
- 仓库地址:https://github.com/spring-projects/spring-framework
- 配置特点:使用自定义规则集,在 CI 流水线中作为质量门禁,结合 Checkstyle 和 SpotBugs 形成完整的代码质量工具链
4. 工具配置说明
4.1 配置文件说明
PMD 的规则集通过 XML 文件配置,这是 PMD 最核心的配置方式。规则集文件定义了要启用哪些规则、排除哪些规则以及规则的参数调整。
| 配置文件 | 格式 | 用途 |
|---|---|---|
ruleset.xml |
XML | 规则集定义:引用规则分类、排除规则、覆盖规则属性、文件排除模式 |
pom.xml(<pmdConfig> 节) |
XML | Maven maven-pmd-plugin 中引用 ruleset.xml 并配置构建行为 |
规则集配置指南:https://docs.pmd-code.org/latest/pmd_userdocs_making_rulesets.html
4.2 ruleset.xml 配置详解
ruleset.xml 是 PMD 的主配置文件,通过引用规则分类、排除规则、覆盖属性来定制检查规则。
配置项说明:
| 配置项 | 类型 | 说明 |
|---|---|---|
<ruleset name> |
string | 规则集名称 |
<description> |
string | 规则集描述 |
<rule ref> |
string | 引用规则分类(如 category/java/bestpractices.xml)或单个规则(如 category/java/errorprone.xml/EmptyCatchBlock) |
<rule ref> 下的 <exclude name> |
string | 从引用的分类中排除指定规则 |
<rule ref> 下的 <properties> |
map | 覆盖规则属性,每项含 <property name value> |
<exclude-pattern> |
string | 文件排除正则,匹配的文件不参与检查 |
规则属性覆盖示例:
通过 <properties> 节点覆盖单个规则的默认参数:
<!-- 覆盖 NPathComplexity 的报告级别阈值 -->
<rule ref="category/java/design.xml/NPathComplexity">
<properties>
<property name="reportLevel" value="200"/>
</properties>
</rule>
推荐配置示例:
以下是一个面向 Java 项目的推荐规则集配置,涵盖了最佳实践、代码风格、设计、错误倾向等核心类别。每条规则均附说明。
<?xml version="1.0"?>
<ruleset name="Recommended Java Rules"
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0
https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
<description>
PMD 推荐规则集 - 适用于 Java 项目的综合代码质量检查配置。
涵盖最佳实践、代码风格、设计、错误倾向等核心类别。
</description>
<!-- ============================================ -->
<!-- Best Practices(最佳实践) -->
<!-- ============================================ -->
<rule ref="category/java/bestpractices.xml">
<!-- 排除:JUnit 测试方法应为包级别访问(某些框架要求 public) -->
<exclude name="JUnitJupiterTestShouldBePackagePrivate"/>
<!-- 排除:JUnit5 测试不应为包级别(同上) -->
<exclude name="JUnit5TestShouldBePackagePrivate"/>
</rule>
<!-- ============================================ -->
<!-- Code Style(代码风格) -->
<!-- ============================================ -->
<rule ref="category/java/codestyle.xml">
<!-- 排除:控制语句必须使用大括号(部分团队允许单行不加括号) -->
<exclude name="ControlStatementBraces"/>
<!-- 排除:短变量名(某些场景下短变量名更清晰) -->
<exclude name="ShortVariable"/>
<!-- 排除:长变量名(某些场景下需要描述性命名) -->
<exclude name="LongVariable"/>
<!-- 排除:方法命名约定(某些框架有特殊命名要求) -->
<exclude name="MethodNamingConventions"/>
<!-- 排除:局部变量命名约定 -->
<exclude name="LocalVariableNamingConventions"/>
</rule>
<!-- ============================================ -->
<!-- Design(设计) -->
<!-- ============================================ -->
<rule ref="category/java/design.xml">
<!-- 排除:NPath 复杂度(与圈复杂度存在重叠) -->
<exclude name="NPathComplexity"/>
<!-- 排除:过多导入(某些大型项目需要较多导入) -->
<exclude name="ExcessiveImports"/>
</rule>
<!-- ============================================ -->
<!-- Error Prone(错误倾向) -->
<!-- ============================================ -->
<rule ref="category/java/errorprone.xml">
<!-- 排除:空 catch 块(某些框架要求空 catch 块) -->
<!-- 如需保留,可配置忽略特定异常类型 -->
</rule>
<!-- ============================================ -->
<!-- Multithreading(多线程) -->
<!-- ============================================ -->
<rule ref="category/java/multithreading.xml">
<!-- 仅保留关键的多线程规则 -->
<exclude name="DoNotUseThreads"/>
</rule>
<!-- ============================================ -->
<!-- Performance(性能) -->
<!-- ============================================ -->
<rule ref="category/java/performance.xml">
<!-- 排除:避免在循环中实例化对象(某些场景需要) -->
<exclude name="AvoidInstantiatingObjectsInLoops"/>
</rule>
<!-- ============================================ -->
<!-- Security(安全) -->
<!-- ============================================ -->
<rule ref="category/java/security.xml"/>
<!-- ============================================ -->
<!-- 文件排除 -->
<!-- ============================================ -->
<!-- 排除自动生成的代码 -->
<exclude-pattern>.*/generated/.*</exclude-pattern>
<!-- 排除测试代码(如需单独配置测试规则) -->
<!-- <exclude-pattern>.*/src/test/.*</exclude-pattern> -->
</ruleset>
快速开始规则集:
PMD 提供了内置的快速开始规则集,适合新项目快速启用:
# 使用内置快速开始规则集
pmd check -d src/main/java -R rulesets/java/quickstart.xml -f text
rulesets/java/quickstart.xml 包含了 PMD 推荐的常用规则子集,适合作为初始配置的起点。
4.3 规则分类说明
PMD 将所有内置规则分为以下 8 个统一类别(从 6.0.0 开始):
| 类别 | 说明 | 规则集路径 |
|---|---|---|
| Best Practices | 强制执行普遍接受的最佳实践,如使用 equals() 比较字符串、正确关闭资源等 |
category/java/bestpractices.xml |
| Code Style | 统一编码风格,包括命名约定、代码结构、大括号使用等 | category/java/codestyle.xml |
| Design | 发现设计问题,如过高的圈复杂度、过多的方法参数、God Class 等 | category/java/design.xml |
| Documentation | 确保代码文档的完整性,如类和方法注释 | category/java/documentation.xml |
| Error Prone | 检测容易出错、令人困惑或可能导致运行时错误的代码结构 | category/java/errorprone.xml |
| Multithreading | 标记多线程环境中潜在的问题,如不安全的同步、死锁风险等 | category/java/multithreading.xml |
| Performance | 标记可能导致性能问题的次优代码,如不必要的对象创建 | category/java/performance.xml |
| Security | 标记潜在的安全漏洞 | category/java/security.xml |
4.4 第三方规则集
| 规则集 | 说明 | 链接 |
|---|---|---|
| Alibaba P3C | 阿里巴巴 Java 编码规范 PMD 实现,国内使用最广泛 | https://github.com/alibaba/p3c |
Java 规则完整参考:https://docs.pmd-code.org/latest/pmd_rules_java.html
5. 主流集成方式
5.1 Maven 集成(生态主流,优先)
Maven 是 Java 生态中最主流的构建工具,maven-pmd-plugin 是 PMD 最推荐的集成方式。当前 Maven PMD 插件默认使用 PMD 7.x(maven-pmd-plugin 3.22.0+)。
<properties>
<pmd.version>7.25.0</pmd.version>
<maven-pmd-plugin.version>3.26.0</maven-pmd-plugin.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>${maven-pmd-plugin.version}</version>
<dependencies>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-core</artifactId>
<version>${pmd.version}</version>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-java</artifactId>
<version>${pmd.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<configuration>
<!-- 规则集配置 -->
<rulesets>
<ruleset>${project.basedir}/config/pmd/ruleset.xml</ruleset>
</rulesets>
<!-- 源代码编码 -->
<sourceEncoding>UTF-8</sourceEncoding>
<!-- 目标 JDK 版本 -->
<targetJdk>${maven.compiler.target}</targetJdk>
<!-- 排除生成的代码 -->
<excludeRoots>
<excludeRoot>target/generated-sources</excludeRoot>
</excludeRoots>
<!-- 输出目录 -->
<outputDirectory>${project.build.directory}/pmd-report</outputDirectory>
<!-- 是否在违规时失败 -->
<failOnViolation>true</failOnViolation>
<!-- 打印失败错误 -->
<printFailingErrors>true</printFailingErrors>
<!-- 失败优先级(1-5,1最严重) -->
<failurePriority>3</failurePriority>
<!-- 启用增量分析 -->
<analysisCache>true</analysisCache>
</configuration>
<executions>
<execution>
<id>pmd-check</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
常用 Maven 命令:
# 生成 PMD 报告(不中断构建)
mvn pmd:pmd
# 执行 PMD 检查(违规时中断构建)
mvn pmd:check
# 执行 CPD 重复代码检测
mvn pmd:cpd
# 跳过 PMD 检查
mvn verify -Dpmd.skip=true
Maven PMD 插件文档:https://maven.apache.org/plugins/maven-pmd-plugin/
增量检查:在 pom.xml 中启用增量分析(maven-pmd-plugin 3.8+ 支持),通过缓存分析数据跳过未修改文件。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<configuration>
<!-- 启用增量分析 -->
<analysisCache>true</analysisCache>
<!-- 可选:指定缓存文件位置(默认如下) -->
<analysisCacheLocation>${project.build.directory}/pmd/pmd.cache</analysisCacheLocation>
</configuration>
</plugin>
5.2 pre-commit 集成
PMD 分析 Java 源代码,pre-commit hook 依赖本地 JDK 和构建工具链。
注意:以下配置使用
language: system,依赖本地已安装的 JDK 和 Maven/Gradle,执行环境需要预先完成项目编译。
repos:
- repo: local
hooks:
- id: pmd-check
name: PMD Static Analysis
entry: bash -c 'mvn pmd:check -q'
language: system
types: [java]
pass_filenames: false
安装钩子:
pip install pre-commit
pre-commit install
说明:
pass_filenames: false表示不将变更文件列表传给 hook,因为 PMD 通过 Maven 插件管理分析范围。language: system要求本地环境已安装 JDK 和 Maven。
增量检查:pre-commit 框架默认只对暂存区中变更的 .java 文件触发 hook。由于 PMD 的 local hook 使用 pass_filenames: false(让 Maven 自行管理检查范围),实际增量由 Maven 构建 + PMD 的 --cache 缓存机制决定。pre-commit 负责"何时触发"(只在有 .java 文件变更时),PMD 的 --cache 缓存负责"加速检查"(跳过未修改文件)。CI 中可通过 pre-commit run --all-files 做全量检查。
# .pre-commit-config.yaml(增量推荐配置)
- repo: local
hooks:
- id: pmd-check
name: PMD check
entry: mvn pmd:check
language: system
files: \.java$
pass_filenames: false # 由 Maven + PMD --cache 控制增量
5.3 IDE 集成
VS Code
安装 PMD for Java 扩展:
- 打开 VS Code,进入扩展市场
- 搜索 "PMD for Java" 并安装
- 在项目根目录创建
.vscode/settings.json:
{
"pmd.ruleset": "config/pmd/ruleset.xml",
"pmd.executable": "path/to/pmd-bin-7.25.0/bin/pmd",
"pmd.jdkVersion": "17"
}
IntelliJ IDEA
安装 PMD 或 PMD X 插件:
- 打开
Settings>Plugins,搜索 "PMD" 并安装 - 配置 PMD:
Settings>Other Settings>PMD - 指定 PMD 安装路径和规则集文件路径
- 右键点击代码目录或文件,选择
Run PMD执行检查
PMD IDE 插件文档:https://docs.pmd-code.org/latest/pmd_userdocs_tools_ide_plugins.html
5.4 命令行使用方式
安装
# Linux / macOS
curl -OL https://github.com/pmd/pmd/releases/download/pmd_releases%2F7.25.0/pmd-dist-7.25.0-bin.zip
unzip pmd-dist-7.25.0-bin.zip
# 添加到 PATH
export PATH=$PATH:$HOME/pmd-bin-7.25.0/bin
# Windows (手动)
# 下载并解压到 C:\pmd-bin-7.25.0
# 将 C:\pmd-bin-7.25.0\bin 添加到 PATH
pmd check -- 代码分析
# 基本用法:分析源代码目录
pmd check -d src/main/java -R rulesets/java/quickstart.xml -f text
# 使用自定义规则集
pmd check -d src/main/java -R config/pmd/ruleset.xml -f html
# 指定语言版本
pmd check -d src/main/java -R rulesets/java/quickstart.xml --use-version java-17
# 输出格式:text / html / xml / json / csv / sarif
pmd check -d src/main/java -R rulesets/java/quickstart.xml -f sarif -o pmd-report.sarif
# 排除特定文件(PMD 7.14.0+)
pmd check -d src/main/java -R rulesets/java/quickstart.xml --exclude "src/main/java/generated/**"
# 指定最低优先级(1最严重,5最不严重)
pmd check -d src/main/java -R rulesets/java/quickstart.xml --minimum-priority 3
# 启用增量分析缓存
pmd check -d src/main/java -R rulesets/java/quickstart.xml --cache .pmdcache
# 禁用增量分析(全量扫描)
pmd check -d src/main/java -R rulesets/java/quickstart.xml --no-cache
# 指定辅助类路径(用于类型解析)
pmd check -d src/main/java -R rulesets/java/quickstart.xml --aux-classpath "lib/*:target/classes"
# 多线程分析(使用 2 个线程)
pmd check -d src/main/java -R rulesets/java/quickstart.xml -t 2
pmd cpd -- 复制粘贴检测
# 检测重复代码(默认最少 100 个 token)
pmd cpd -d src/main/java --minimum-tokens 100 -f text
# 指定语言
pmd cpd -d src/main/java --language java --minimum-tokens 50 -f xml
# 输出 HTML 格式报告
pmd cpd -d src/main/java --minimum-tokens 100 -f html -o cpd-report.html
# 同时检测多个目录
pmd cpd -d src/main/java:src/test/java --minimum-tokens 100 -f text
其他子命令
# 启动 PMD 规则设计器(GUI,需要 JavaFX)
pmd designer
# 启动 CPD GUI
pmd cpd-gui
# 查看版本
pmd --version
# 查看帮助
pmd check --help
pmd cpd --help
PMD CLI 参考文档:https://docs.pmd-code.org/latest/pmd_userdocs_cli_reference.html
增量检查:PMD 命令行原生支持 --cache 参数实现增量分析,也支持基于 Git 的命令行增量方案。
--cache 参数(增量分析)
# 首次运行(全量分析,生成缓存)
pmd check -d src/main/java -R ruleset.xml -f text --cache .pmd-cache
# 后续运行(增量分析,跳过未修改文件)
pmd check -d src/main/java -R ruleset.xml -f text --cache .pmd-cache
PMD 缓存默认存储在用户临时目录,可通过
--cache参数指定缓存文件路径。缓存文件记录了每个文件的分析结果和最后修改时间,下次运行时自动跳过未修改的文件。
缓存失效条件
以下情况会导致缓存失效,PMD 将重新分析所有文件:
- 规则集变更:修改了
ruleset.xml或引用的规则集 - PMD 版本升级:不同版本的 PMD 缓存不兼容
- 文件被删除:缓存中记录的文件被删除会触发缓存更新
- 文件内容变更:文件被修改(通过文件最后修改时间和内容哈希判断)
基于 Git 的命令行增量方案
# 获取变更的 Java 文件列表并分析
git diff --name-only --diff-filter=ACMR HEAD -- '*.java' | xargs pmd check -R ruleset.xml -f text
# 仅分析暂存区的 Java 文件
git diff --name-only --cached -- '*.java' | xargs pmd check -R ruleset.xml -f text
注意:此方案仅分析变更文件本身,不分析依赖这些文件的其他文件。PMD 的静态分析通常不依赖跨文件分析(每个文件独立分析),因此此方案比 Mypy 等类型检查工具更适合文件级增量。
CI 脚本调用:
GitHub Actions
在 .github/workflows/pmd-check.yml 中配置:
name: PMD Code Check
on: [push, pull_request]
permissions:
contents: read
jobs:
pmd-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"
- name: Cache Maven dependencies
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Run PMD Check
run: mvn pmd:check -Dpmd.skip=false
- name: Upload PMD Report
if: always()
uses: actions/upload-artifact@v4
with:
name: pmd-report
path: target/pmd-report/
GitLab CI
在 .gitlab-ci.yml 中配置:
pmd-check:
stage: test
image: maven:3.9-eclipse-temurin-17
script:
- mvn pmd:check -B
artifacts:
when: always
paths:
- target/pmd-report/
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'
增量检查:CI/CD 场景下可利用 PMD 的 --cache 参数或 Maven 的 analysisCache 实现增量分析。
GitHub Actions(增量:使用 --cache)
name: PMD Check (Incremental)
on: [push, pull_request]
jobs:
pmd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: "21"
distribution: "temurin"
- name: Cache PMD results
uses: actions/cache@v4
with:
path: .pmd-cache
key: pmd-${{ runner.os }}-${{ hashFiles('**/*.java') }}
- name: Run PMD with incremental cache
run: |
wget -q https://github.com/pmd/pmd/releases/download/pmd_releases%2F7.16.0/pmd-dist-7.16.0-bin.zip
unzip -q pmd-dist-7.16.0-bin.zip
./pmd-bin-7.16.0/bin/pmd check -d src/main/java -R ruleset.xml -f text --cache .pmd-cache
GitLab CI(增量:使用 Maven analysisCache)
# .gitlab-ci.yml
pmd-check:
image: maven:3.9-eclipse-temurin-21
script:
- mvn pmd:check -DanalysisCache=true
cache:
paths:
- target/pmd/pmd.cache
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
5.5 Gradle 集成
Gradle 内置了 PMD 插件,开箱即用。使用 PMD 7 需要 Gradle 8.6+。
// build.gradle
plugins {
id 'pmd'
}
pmd {
// PMD 版本(PMD 7 需要 Gradle 8.6+)
toolVersion = "7.25.0"
// 使用自定义规则集文件(推荐)
ruleSetFiles = files("config/pmd/ruleset.xml")
// 清空默认规则集,避免与自定义规则集冲突
ruleSets = []
// 是否忽略失败(true=不中断构建,false=违规时中断构建)
ignoreFailures = false
// 报告输出目录
reportsDir = file("${buildDir}/reports/pmd")
}
Kotlin DSL 写法:
// build.gradle.kts
plugins {
pmd
}
pmd {
toolVersion = "7.25.0"
ruleSetFiles = files("config/pmd/ruleset.xml")
ruleSets = emptyList()
isIgnoreFailures = false
}
常用 Gradle 命令:
# 对 main 源码执行 PMD 检查
./gradlew pmdMain
# 对 test 源码执行 PMD 检查
./gradlew pmdTest
# 执行所有 PMD 检查
./gradlew pmd
Gradle PMD 插件文档:https://docs.gradle.org/current/userguide/pmd_plugin.html
增量检查:Gradle PMD 插件默认支持增量任务(Gradle 的 up-to-date 检查),只需确保使用 ./gradlew pmdMain 而非 --rerun-tasks,Gradle 会自动处理增量(仅重新分析变更的文件)。
6. 告警抑制(屏蔽)方法
PMD 提供了多种告警抑制方法,从代码级别到规则集级别均可控制。官方文档:https://docs.pmd-code.org/latest/pmd_userdocs_suppressing_warnings.html
6.1 通过代码屏蔽
@SuppressWarnings 注解(推荐)
在 Java 代码中使用注解抑制特定规则或所有 PMD 警告:
// 抑制类中所有 PMD 警告
@SuppressWarnings("PMD")
public class MyClass {
// ...
}
// 抑制特定规则
@SuppressWarnings("PMD.UnusedLocalVariable")
public void myMethod() {
int x = 10; // 不会报 UnusedLocalVariable 警告
}
// 抑制多个规则
@SuppressWarnings({"PMD.UnusedLocalVariable", "PMD.UnusedPrivateMethod"})
public void myMethod() {
// ...
}
// JDK 标准注解也会被 PMD 识别,抑制 unused 规则集中的所有规则
@SuppressWarnings("unused")
public class Bar {
void bar() {
int foo; // 抑制 UnusedLocalVariable
}
private void foobar(){} // 抑制 UnusedPrivateMethod
}
官方文档参考:https://docs.pmd-code.org/latest/pmd_userdocs_suppressing_warnings.html#annotations
NOPMD 注释标记
在代码行末尾添加 // NOPMD 注释来抑制该行的警告:
public class Bar {
// 'bar' 由本地方法访问,需要抑制警告
private int bar; // NOPMD
public void foo() {
try {
someMethod();
} catch (FileNotFoundException e) {} // NOPMD - 此异常实际上不会发生
}
}
注意:
// NOPMD标记必须与违规代码在同一行。例如,要抑制空 if 语句的警告,需要将// NOPMD放在包含if关键字的行。
也可以通过 --suppress-marker 选项自定义抑制标记:
pmd check -d Foo.java -R category/java/bestpractices.xml --suppress-marker TURN_OFF_WARNINGS
官方文档参考:https://docs.pmd-code.org/latest/pmd_userdocs_suppressing_warnings.html#nopmd-comment
6.2 通过工具配置文件屏蔽
violationSuppressRegex(正则表达式抑制)
在规则集 XML 中,通过正则表达式匹配违规消息来抑制特定场景的警告:
<!-- 抑制特定参数名未使用的警告 -->
<rule ref="category/java/bestpractices.xml/UnusedFormalParameter">
<properties>
<property name="violationSuppressRegex"
value=".*'mySpecialParameterName'.*"/>
</properties>
</rule>
<!-- 抑制特定消息模式的警告 -->
<rule ref="category/java/design.xml/CyclomaticComplexity">
<properties>
<property name="violationSuppressRegex"
value=".*in class.*Service.*"/>
</properties>
</rule>
violationSuppressXPath(XPath 抑制)
在规则集 XML 中,通过 XPath 表达式匹配 AST 节点来抑制特定代码结构的警告:
<!-- 抑制特定方法中的警告 -->
<rule ref="category/java/bestpractices.xml/UnusedFormalParameter">
<properties>
<property name="violationSuppressXPath"
value="./ancestor-or-self::MethodDeclaration[@Name='mySpecialMethod']"/>
</properties>
</rule>
<!-- 抑制名称包含 Bean 的类中的警告 -->
<rule ref="category/java/design.xml/TooManyMethods">
<properties>
<property name="violationSuppressXPath"
value="./ancestor-or-self::ClassDeclaration[contains(@SimpleName, 'Bean')]"/>
</properties>
</rule>
规则集级别排除
在规则集 XML 中直接排除不需要的规则或文件:
<!-- 排除整个规则分类中的特定规则 -->
<rule ref="category/java/codestyle.xml">
<exclude name="ShortVariable"/>
<exclude name="LongVariable"/>
<exclude name="ShortMethodName"/>
</rule>
<!-- 通过文件模式排除特定文件 -->
<exclude-pattern>.*/generated/.*</exclude-pattern>
<exclude-pattern>.*/model/.*</exclude-pattern>
<exclude-pattern>.*/\.*/.*</exclude-pattern>
规则集配置指南:https://docs.pmd-code.org/latest/pmd_userdocs_making_rulesets.html
6.3 通过工具命令行参数屏蔽
# 排除特定文件(PMD 7.14.0+)
pmd check -d src/main/java -R rulesets/java/quickstart.xml --exclude "src/main/java/generated/**"
# 通过排除文件列表排除(PMD 7.14.0+)
pmd check -d src/main/java -R rulesets/java/quickstart.xml --exclude-file-list exclude-list.txt
# 指定最低优先级(屏蔽低优先级告警)
pmd check -d src/main/java -R rulesets/java/quickstart.xml --minimum-priority 3
# 自定义抑制标记
pmd check -d src/main/java -R rulesets/java/quickstart.xml --suppress-marker TURN_OFF_WARNINGS
PMD CLI 参考:https://docs.pmd-code.org/latest/pmd_userdocs_cli_reference.html
6.4 通过集成调度工具屏蔽
Maven excludes 配置
通过 maven-pmd-plugin 的 excludeRoots 和 includes/excludes 参数排除特定文件或目录:
<configuration>
<excludeRoots>
<excludeRoot>target/generated-sources</excludeRoot>
</excludeRoots>
<includes>
<include>**/*.java</include>
</includes>
<excludes>
<exclude>**/generated/**</exclude>
</excludes>
</configuration>
Maven PMD 插件文档:https://maven.apache.org/plugins/maven-pmd-plugin/
Gradle exclude 配置
pmd {
ruleSetFiles = files("config/pmd/ruleset.xml")
ruleSets = []
exclude = ['**/generated/**', '**/model/**']
}
Gradle PMD 插件文档:https://docs.gradle.org/current/userguide/pmd_plugin.html
6.5 查找未使用的抑制
PMD 7.14.0 起提供了 UnnecessaryWarningSuppression 规则,用于发现未使用的 @SuppressWarnings("PMD.xxx") 和 // NOPMD 注释:
<rule ref="category/java/bestpractices.xml/UnnecessaryWarningSuppression"/>
6.6 告警抑制方法总结
| 方法 | 粒度 | 适用场景 | 是否需要修改代码 | 官方文档 |
|---|---|---|---|---|
@SuppressWarnings("PMD.xxx") |
类/方法/字段 | 已确认的误报或可接受的例外 | 是 | Annotations |
// NOPMD |
单行 | 临时抑制特定行的告警 | 是 | NOPMD comment |
violationSuppressRegex |
规则实例 | 通过消息正则匹配批量抑制 | 否 | Regex suppression |
violationSuppressXPath |
AST 节点 | 通过 XPath 精确匹配代码结构抑制 | 否 | XPath suppression |
规则集 <exclude> |
规则级别 | 排除不需要的规则 | 否 | Making rulesets |
<exclude-pattern> |
文件/目录 | 排除特定文件或目录 | 否 | Making rulesets |
CLI --exclude |
文件/目录 | 临时排除特定路径 | 否 | CLI reference |
CLI --minimum-priority |
优先级级别 | 屏蔽低优先级告警 | 否 | CLI reference |
Maven excludeRoots |
目录 | 排除生成代码目录 | 否 | Maven plugin |
UnnecessaryWarningSuppression |
抑制标记 | 清理过时的抑制注释 | 否 | Rule reference |