- 静态分析
- 代码质量
【免费下载链接】pmd
An extensible multilanguage static code analyzer.
PMD 是业界广泛使用的可扩展多语言静态代码分析器,其 7.x 系列从 2023 年的首个 RC 一路演进到 2026 年的 7.28.0,完整经历了「大版本重构 → 逐版本打磨」的整个过程。本文以仓库内的 历史发布说明 为骨架,系统梳理 PMD 7.x 的版本时间线、7.0.0 的架构级变革、Java 语言版本支持策略、规则体系演进、Kotlin 类型感知分析、CPD 能力扩展以及安全与发布工程实践,帮助读者快速建立对 PMD 7 全貌的认知,并为升级、选型与自定义规则开发提供依据。
PMD 7 新 CLI 演示动画
一、PMD 7.x 版本时间线总览
7.x 系列采用固定节奏的 minor release 模式(通常每 27~35 天一个版本),每个版本以「新特性(New and noteworthy)→ 规则变更 → 修复 → API 变更 → 合并的 PR → 依赖升级 → 统计」的标准结构发布。从发布说明统计看,各版本发布节奏稳定,例如 7.0.0 距上一大版本(6.55.0)相隔 390 天,而此后的小版本间隔大多在一个月以内。
| 版本 | 发布日期 | 核心主题 |
|---|---|---|
| 7.0.0 | 2024-03-22 | 大版本重构:Java 21/22、Kotlin/Swift、Apex 新解析器、CPD 新语言、统一 CLI、XPath 3.1 |
| 7.1.0 | 2024-04-26 | 更稳健的 CPD 报告;UnnecessaryVarargsArrayCreation等新规则 |
| 7.2.0 | 2024-05-31 | 集合以 XPath 序列属性形式暴露 |
| 7.3.0 | 2024-06-28 | 移除 pmd-compat6;CPD XML 报告 schema 化;新增退出码 5 |
| 7.4.0 | 2024-07-26 | AvoidNonRestrictiveQueries(Apex 性能) |
| 7.5.0 | 2024-08-30 | Java 23 支持;AvoidSynchronizedStatement |
| 7.6.0 | 2024-09-27 | Git 默认分支切换为 main |
| 7.7.0 | 2024-10-25 | C++ CPD 支持忽略字面量与标识符;JUnit/switch 规则批量重命名 |
| 7.8.0 | 2024-11-29 | QueueableWithoutFinalizer(Apex) |
| 7.9.0 | 2024-12-27 | CPD 支持 Rust |
| 7.10.0 | 2025-01-31 | Java 24 支持;ExhaustiveSwitchHasDefault;更换 GPG 签名密钥 |
| 7.11.0 | 2025-02-28 | AvoidStatefulDatabaseResult;发布二进制签名 |
| 7.12.0 | 2025-03-28 | ImplicitFunctionalInterface |
| 7.13.0 | 2025-04-25 | 官方 Docker 镜像;语言方言(Dialect)实验性支持 |
| 7.14.0 | 2025-05-30 | CLI 默认多线程(-t 1C);UnnecessaryWarningSuppression |
| 7.15.0 | 2025-06-27 | AvoidBooleanMethodParameters(Apex) |
| 7.16.0 | 2025-07-25 | Java 25 支持;CPD 支持 CSS;ReplaceJavaUtilCalendar/Date |
| 7.17.0 | 2025-09-12 | 命名规范、ModifierOrder、CollectionTypeMismatch等 9 个 Java 新规则;CPD Markdown 报告 |
| 7.18.0 | 2025-10-31 | 构建要求提升至 Java 17;IdenticalConditionalBranches等新规则 |
| 7.19.0 | 2025-11-28 | EnumComparison、AvoidFutureAnnotation;Apex/PLSQLNcssCount合并 |
| 7.20.0 | 2025-12-30 | OnlyOneReturn新增ignoredMethodNames |
| 7.21.0 | 2026-01-30 | Java 26 支持;构建要求提升至 Java 21;枚举属性值统一为小驼峰 |
| 7.22.0 | 2026-02-27 | 修复 VBHTML/YAHTML 报告存储型 XSS;UnnecessaryInterfaceDeclaration |
| 7.23.0 | 2026-03-27 | 修复类版本 |
| 7.24.0 | 2026-04-24 | AvoidInterfaceAsMapKey、OverridingThreadRun |
| 7.25.0 | 2026-05-29 | ANTLR 升级至 4.13.2;违规报告位置精确化(单行警告) |
| 7.26.0 | 2026-06-29 | Swift 语法错误按处理错误上报;WrongTestAnnotation、AssertEqualsArgumentOrder |
| 7.27.0 | 2026-08-28 | Java 27 支持;Apex 67.0;Kotlin 类型感知分析(auxClasspath) |
| 7.28.0 | 2026-09-25 | Kotlin XPath 函数与类型属性;OnDemandImport、InternalApiUsage等 6 个新规则 |
二、7.0.0:一次架构级的全面重构
7.0.0 是自 PMD 6 之后近 390 天的首个大版本,官方明确声明「它不是 PMD 6.55.0 的直接替代品」,并配套发布了 迁移指南。其变革可以归纳为五个层面。
2.1 Java 模块彻底重写
- 语法更贴近 JLS:Java 语法被大幅重构,与 Java 语言规范(JLS)的一致性显著提升,所有内置规则都针对新 AST 做了适配;
- 类型解析与符号表重写:类型解析框架与符号表按 JLS 重新实现,AST 暴露了更多语义信息(方法调用、字段访问);
- 报告位置收窄:此前方法或类级别的违规会报告整个方法/类的行区间,7.0.0 起只报告方法名或类名标识符所在行,这一行为由各节点对
Node#getReportLocation()的重写控制,并影响CognitiveComplexity等多个规则。
2.2 语言版图扩张
- Java 21/22:标准特性支持 JEP 456(Unnamed Variables & Patterns)、JEP 440(Record Patterns)、JEP 441(Pattern Matching for switch);预览特性通过
PMD_JAVA_OPTS=--enable-preview配合--use-version java-22-preview启用; - Kotlin(稳定):支持 Kotlin 1.8 语法,首批内置 2 条规则(
FunctionNameTooShort、OverrideBothEqualsAndHashcode),在 pmd-kotlin 模块中实现; - Swift(新增):有限支持 Swift 5.9(宏展开),首批 4 条内置规则(
ForceCast、ForceTry、ProhibitedInterfaceBuilder、UnavailableFunction); - Apex 换芯:将闭源的 Jorje 解析器替换为完全开源的 apex-parser(ANTLR 语法)+ Google Summit-AST(ANTLR 解析树转 AST)组合,可解析 User Mode Database Operations 与
??空值合并运算符,Apex 支持推进到 60.0(Spring '24); - CPD 新增语言:Coco、Julia、TypeScript、Apache Velocity(VTL),并改进 C++(
--ignore-sequences)、Groovy(支持 Groovy 3/4 与CPD-ON/CPD-OFF抑制)与 JavaScript(ES6、注释保留)。
2.3 统一 CLI
7.0.0 将原来分散的工具整合为单一脚本pmd(Windows 下pmd.bat),通过子命令区分功能:
pmd check # 运行 PMD 规则分析项目 pmd cpd # 运行 CPD(复制粘贴检测器) pmd designer # 运行 PMD Rule Designer同时为pmd check增加了进度条与 shell 补全支持。完整的参数说明可参考 CLI 参考文档。
2.4 XPath 3.1 与规则编写体系
- XPath 规则引擎从 XPath 1.0 升级到 3.1(基于 Saxon,移除 Jaxen),所有规则的
violationSuppressXPath属性默认按 XPath 3.1 求值; - 配套提供了 Node Stream API、Metrics 框架、测试框架、语言生命周期(Language Lifecycle)与语言属性(Language Properties)等新能力。
2.5 API 清理与兼容层
- 旧的属性类(
IntProperty、StringProperty等)被移除,统一改用PropertyFactory;多值属性分隔符从|改为逗号(,,可用反斜杠转义);数值属性的min/max变为可选; - 提供新的程序化 CPD 入口 CpdAnalysis(对应 pmd-core 中的
net.sourceforge.pmd.cpd包); - 为 maven-pmd-plugin 提供
pmd-compat6兼容模块(后续在 7.3.0 中正式移除); - 大量历史废弃规则与规则集(
rulesets/java/basic.xml等 PMD 5 时代遗留)被清理。
三、Java 语言版本支持:21 → 27 的演进路线
PMD 7 对 Java 的支持采用「标准特性 + 预览特性」双轨机制:标准特性直接由对应语言版本(如java-21)解析,预览特性则需要两步操作:设置环境变量PMD_JAVA_OPTS=--enable-preview并选择NN-preview版本。
export PMD_JAVA_OPTS=--enable-preview pmd check --use-version java-25-preview ...各版本演进要点:
- 7.0.0(Java 21/22):Record Patterns、Pattern Matching for switch、Unnamed Variables & Patterns 正式支持;
- 7.5.0(Java 23):四个预览特性(JEP 455/476/477/482);注意 String Templates 预览特性自 Java 23 起不再存在;
- 7.10.0(Java 24):四个预览特性(JEP 488/492/494/495);同年 7.10.0 移除了为 String Templates 引入的实验性 AST 节点(
ASTTemplate等); - 7.16.0(Java 25):JEP 511/512/513 三个新标准特性 + JEP 507 预览;
ASTImportDeclaration#isModuleImport、ASTImplicitClassDeclaration等 API 转正为稳定; - 7.21.0(Java 26):JEP 530 预览;同版本构建要求提升到 Java 21(PMD 运行时仍保持 Java 8 兼容);
- 7.27.0(Java 27):JEP 532 预览,
java-27-preview版本可选。
每个新大版本都会移除更早的 preview 版本(例如 7.16.0 移除java-23-preview,7.21.0 移除java-24-preview,7.27.0 移除java-25-preview),使用方需跟随升级。
四、规则体系的持续演进
4.1 新规则:按语言与类别持续扩充
7.x 每个 minor release 几乎都会带来新规则,主要集中在 Java,其次是 Apex、Kotlin、Swift、PL/SQL 与 XML。按时间归纳的亮点规则包括:
- Best Practices:
UnnecessaryVarargsArrayCreation(7.1)、UseEnumCollections(7.3,报告以枚举为键的HashMap/HashSet,建议改用枚举专用集合)、UnusedLocalVariable大幅增强、ExhaustiveSwitchHasDefault(7.10)、ImplicitFunctionalInterface(7.12)、RelianceOnDefaultCharset/VariableCanBeInlined/CollectionTypeMismatch(7.17)、LabeledStatement/UnusedLabel(7.18)、EnumComparison(7.19)、OnDemandImport/TypeNameMismatch(7.28); - Codestyle:
UseExplicitTypes(7.0,报告var用法)、UnnecessaryBoxing(7.0)、LambdaCanBeMethodReference(7.1)、ModifierOrder/TypeParameterNamingConventions(7.17,后者取代GenericsNaming)、UnnecessaryBlock(7.25); - Error Prone:
ConfusingArgumentToVarargsMethod(7.1)、UselessPureMethodCall(7.17)、IdenticalConditionalBranches(7.18)、UnsupportedJdkApiUsage(7.21,覆盖sun.*与sun.misc.Unsafe等非便携 API,取代DontImportSun)、WrongTestAnnotation/AssertEqualsArgumentOrder(7.26)、UnusedReturnValue(7.27)、LongLiteralEndingWithLowercaseL/InternalApiUsage(7.28); - Design:
ProtectedMemberInFinalClass(7.27,取代AvoidProtectedFieldInFinalClass与AvoidProtectedMethodInFinalClassNotExtending)、PublicMemberInNonPublicType(7.21); - Apex:
AvoidNonRestrictiveQueries(7.4)、AvoidStatefulDatabaseResult(7.11)、TypeShadowsBuiltInNamespace(7.13)、AvoidFutureAnnotation(7.19)、InvocableClassNoArgConstructor(7.26)、ApexUnitTestClassShouldHaveRunRelevantTestsAnnotation(7.28,针对 SalesforceRunRelevantTests部署场景,标注为 Beta、要求 API 66.0+)。
4.2 规则重命名:更准确的命名与旧名兼容
7.x 进行了两轮大规模规则重命名,旧名仍然可用但被标记为 deprecated:
- 7.7.0:一批以 JUnit 命名的规则改为
UnitTest*前缀以反映其同时适用于 JUnit 5/TestNG 的真实范围(如JUnitTestsShouldIncludeAssert→UnitTestShouldIncludeAssert);一批 switch 相关规则改为同时覆盖语句与表达式(如SwitchStmtsShouldHaveDefault→NonExhaustiveSwitch、DefaultLabelNotLastInSwitchStmt→DefaultLabelNotLastInSwitch、TooFewBranchesForASwitchStatement→TooFewBranchesForSwitch); - 7.17.0:
GenericsNaming→TypeParameterNamingConventions、UnnecessaryLocalBeforeReturn→VariableCanBeInlined、AvoidLosingExceptionInformation/UselessOperationOnImmutable→UselessPureMethodCall; - 7.27.0:
UseUtilityClass→InstantiableUtilityClass。
4.3 关键规则属性的调整示例
- NonThreadSafeSingleton(7.28):
checkNonStaticMethods属性被废弃且不再生效,规则现在同时报告静态与非静态方法(此前默认只报告静态方法),可能导致违规增多。若需恢复抑制非静态方法,可配置 XPath 抑制属性:
<property name="violationSuppressXPath" value=".[ancestor-or-self::MethodDeclaration[1][@Static = false()]]" />- VariableCanBeInlined(7.28):
statementOrderMatters属性被废弃,计划在 PMD 8.0.0 移除; - AvoidCatchingGenericException(7.18):新增
typesThatShouldNotBeCaught属性,并整体从 Design 类别迁移至 Error Prone 类别,同时取代并废弃AvoidCatchingNPE与AvoidCatchingThrowable。从「Design」类别批量引入规则的自定义规则集需要显式补充引用:
<rule ref="category/java/errorprone.xml/AvoidCatchingGenericException" />- OnlyOneReturn(7.20/7.25):新增
ignoredMethodNames(默认compareTo、equals)与allowGuardIfs属性; - 枚举属性值统一(7.21):
AvoidUsingHardCodedIP的checkAddressTypes、ConfusingTernary的nullCheckBranch、ModifierOrder的typeAnnotations、CommentRequired的各属性值全部改为小驼峰形式(如ipv4、any、onType、required),旧值仍可用但会触发废弃警告。
4.4 违规报告位置的精确化(单行警告)
从 7.25.0 起,PMD 持续收敛违规报告位置,目标是从「整类/整块」缩小到「仅相关标识符行」。7.25.0 一次更新了 34 个 Java 规则(包括CyclomaticComplexity、TooManyFields、TooManyMethods、ExcessiveImports、ExcessivePublicCount等),例如CouplingBetweenObjects只报告类标识符、ExhaustiveSwitchHasDefault只报告 switch 关键字、TooManyStaticImports只报告第一个静态导入。这会影响 CI 脚本中的行号断言,升级时需注意。
五、Kotlin:从实验语言到类型感知分析
Kotlin 在 7.0.0 以实验特性引入、随即转正,此后一路获得重点投入:7.25.0 为 Kotlin 引入实验性的 AttributeView 自定义属性机制与PARSE_TIMEOUT_SECONDS语言属性;7.26.0 新增LocalVariableShadowsParameter规则;7.27.0 为 Kotlin 加入基于auxClasspath语言属性的类型感知分析(type-aware analysis);7.28.0 将类型信息接入 XPath 规则层。
5.1 类型属性(7.28,依赖类型解析)
以下属性暴露在声明节点(property、function、class、parameter、catch、for-loop、委托说明符、注解节点)上,仅在配置auxClasspath且 kotlin-type-mapper 完成类型解析后才可用:
@TypeName、@ReturnTypeName、@AnnotationFqNames(注解全限定名)
底层实现位于 KotlinNodeTypeData 及配套的 KotlinTypeName 与 InternalApiBridge,并有 KotlinAuxClasspathIntegrationTest 等测试覆盖。7.28.0 将getTypeName/getReturnTypeName重命名为getType/getReturnType,返回类型从String改为KotlinTypeName(实验性 API 的破坏性变更)。
5.2 通用属性(7.28,不依赖类型解析)
@Mutable、@Identifier、@Name暴露在声明与 import 相关节点上,无论是否配置auxClasspath都始终可用。
5.3 XPath 函数(7.28)
pmd-kotlin 命名空间下新增 7 个 XPath 函数:
| 函数 | 语义 |
|---|---|
pmd-kotlin:typeIs(typeName) | 节点类型为typeName或其子类型时匹配 |
pmd-kotlin:typeIsExactly(typeName) | 仅精确匹配声明的类型(不含子类型) |
pmd-kotlin:hasAnnotation(name) | 节点含指定简单名或全限定名注解时匹配 |
pmd-kotlin:modifiers() | 以序列返回声明的修饰符关键字 |
pmd-kotlin:isNullable() | 声明类型可空(带?)时返回true |
pmd-kotlin:hasUnresolvedReference() | 节点含未解析引用时返回true |
pmd-kotlin:matchesSig(signature) | 按方法签名模式(支持通配符)匹配调用点 |
同时新增的 AST 属性视图类(如KtPropertyDeclarationAttributes、KtFunctionValueParameterAttributes、KtCatchBlockAttributes等)均在net.sourceforge.pmd.lang.kotlin.ast包中,Java 规则可通过KotlinInnerNode#attributes访问,并自动暴露给 XPath。
六、CPD(复制粘贴检测)的持续增强
CPD 在 7.x 中同样持续进化:
- 新语言支持:TypeScript、Julia、Coco、VTL(7.0)、Rust(7.9)、CSS(7.16,随
pmd-css模块发布); - 报告格式:7.3.0 起 CPD 的 XML 报告基于 XSD schema(
cpd-report_1_0_0.xsd),根元素pmd-cpd增加pmdVersion、timestamp、version属性,并将可恢复错误作为<error>元素写入;旧格式可通过 rendererxmlold使用(已废弃);7.17.0 新增 Markdown 报告格式,逐条输出重复代码块,详见 CPD 报告格式文档; - 命令行选项:C++ 支持
--ignore-literal与--ignore-identifiers(7.7),--ignore-sequences(7.0);PMD 与 CPD 从 7.14.0 起共享文件收集参数(如--exclude-file-list、--report-file等); - 匹配质量:7.1.0 修复了重叠/部分重叠重复报告的缺陷,现在只报告最长且不重叠的重复;
- 错误处理:7.3.0 引入退出码 5 表示发生可恢复错误(解析/词法/规则异常),并新增
--no-fail-on-error参数恢复旧行为,--skip-lexical-errors相应废弃。
七、工程、安全与分发实践
- Docker 镜像(7.13):官方镜像支持容器内直接分析,例如
docker run --rm --tty -v $PWD:/src pmdcode/pmd:latest check -d . -R rulesets/java/quickstart.xml; - 签名发布(7.10/7.11):因旧 GPG 密钥口令泄露(CVE-2025-23215),7.10.0 起改用新密钥
A0B5CA1A4E086838签名 Maven Central 制品;7.11.0 起二进制发行包也提供签名,验证方法见 签名发布文档; - 安全修复(7.22):修复 VBHTMLRenderer 与 YAHTMLRenderer 因未转义违规消息导致的存储型 XSS(默认
html格式不受影响,但抑制标记存在类似问题); - 构建要求:7.18.0 起构建需要 Java 17,7.21.0 起需要 Java 21,但产物始终兼容 Java 8 运行时;
- 内部现代化:ANTLR 从 4.9.3 升级到 4.13.2(7.25,ANTRL 语言模块需重新生成词法/语法分析器)、日志体系改用 slf4j、测试迁移到 JUnit 5、默认分支改为
main(7.6)。
八、升级到 PMD 7 的注意事项
综合各版本发布说明,从 6.x 升级到 7.x(以及 7.x 内部跨版本升级)需要重点关注:
- 规则集路径与规则名:
category/vf/*→category/visualforce/*、category/vm/*→category/velocity/*;被移除/重命名的规则需按 迁移指南 逐一核对; - 属性框架:多值属性分隔符改为逗号;统计类规则的
topscore/sigma属性被移除,minimum类型改为整数;Java 规则的方法/类违规位置收窄到标识符; - XPath 版本:
violationSuppressXPath及 XPath 规则默认使用 3.1,从 6.x 升级需重新校验表达式; - CLI/退出码:统一为
pmd check/cpd/designer子命令,注意 7.3.0 起的退出码 5 语义与--no-fail-on-error; - Java preview 版本:跟随每个大版本迁移
NN-preview参数,旧 preview 版本会被移除; - 实验性 API:7.x 存在大量 Experimental API(如 Kotlin 属性视图、语言方言),升级时需关注 API 变更说明 与 japicmp 检查结果。
总结
PMD 7.x 用两年多时间完成了一次「从内核到体验」的全面现代化:Java 模块按 JLS 重写、Kotlin/Swift/CSS/Rust 等语言持续加入、CPD 报告与 CLI 走向统一规范、规则体系在命名、位置与准确性上不断收敛、供应链安全与发布工程逐步完善。对于正在使用或评估 PMD 的团队,本文梳理的版本演进脉络既是升级路线的参照,也是理解 PMD 7 设计取舍(如类型感知分析、单行警告、XPath 3.1)的入口。
- 静态分析
- 代码质量
【免费下载链接】pmd
An extensible multilanguage static code analyzer.
相关推荐
PredictionIO 版本演进全解析:从 0.8.6 到 0.14.0 的架构升级与关键能力盘点
PredictionIO 版本演进全解析:从 0.8.6 到 0.14.0 的架构升级与关键能力盘点 PredictionIO(后文简称 PIO)是一个面向开发
人工智能机器学习后端模型推理服务大数据Proxmark3 FM11RF08S 恢复脚本:Windows 和 Termux 也能用了
Proxmark3 FM11RF08S 恢复脚本:Windows 和 Termux 也能用了 酒店卡读卡读到「静态加密 nonce」报错、标准攻击全部失效时,P
渗透测试嵌入式物联网网络安全react-diagrams 7.x 版本演进实录:demo 项目从 Lerna 到 Pnpm + Changesets 的工程化重构全解析
react diagrams 7.x 版本演进实录:demo 项目从 Lerna 到 Pnpm + Changesets 的工程化重构全解析 本篇文章以 dia
UI组件前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考