- 静态分析
- 代码质量
【免费下载链接】pmd
An extensible multilanguage static code analyzer.
本文基于 PMD 官方文档 bld PMD Extension,介绍如何将 PMD 静态代码分析集成到 bld 构建系统中。bld 是一款允许你用纯 Java 编写构建逻辑的新型构建系统,通过其官方 PMD 扩展,你可以像声明一个普通 Java 方法那样定义静态分析任务,并将其纳入项目的构建生命周期。阅读本文后,你将掌握在 bld 构建文件中安装并配置 PMD 扩展、运行 PMD 检查、以及结合 PMD 规则集与辅助类路径(aux classpath)进行深度分析的完整实战方案。
bld 与 PMD 扩展简介
bld 是一个用纯 Java 编写构建逻辑的构建系统。与传统的 XML(Ant/Maven)或 Groovy/Kotlin DSL(Gradle)构建脚本不同,bld 的构建逻辑就是普通的 Java 代码,你可以直接利用 Java 的类型检查、IDE 补全和调试能力来编写和演进构建脚本。
为了在 bld 中运行静态代码分析,官方提供了 PMD Extension。该扩展将 PMD 封装为 bld 的一个操作(Operation),让你可以:
- 在构建文件中声明式地定义 PMD 分析任务;
- 将 PMD 检查纳入构建生命周期(如与测试任务串联执行);
- 直接复用 PMD 的规则集(ruleset)体系与多语言分析能力。
PMD 本身是一个可扩展的多语言静态代码分析器,支持 Java、JavaScript、Apex、XML 等众多语言。本集成方案聚焦于 Java 源码的静态分析,通过 bld 构建系统驱动 PMD 的PmdOperation完成检查。
安装 PMD 扩展
在开始之前,你需要先在 bld 项目中安装 PMD 扩展。安装方法请参阅 bld 官方的 extensions documentation,通常做法是在项目的bld模块或构建配置中引入bld-pmd依赖,使 bld 运行时能够发现PmdOperation类。
安装完成后,你就可以在项目的构建 Java 文件中导入并使用该扩展。需要注意的是,PMD 扩展的运行依赖 PMD 本身的库文件,bld 扩展会负责在构建过程中解析并加载 PMD 及其规则集。
在构建文件中声明 PMD 任务
在 bld 中,构建逻辑被组织为带有@BuildCommand注解的方法。要执行 PMD 检查,你只需要编写一个调用PmdOperation的命令方法。以下是官方文档给出的最小可用示例:
@BuildCommand public void pmd() throws Exception { new PmdOperation() .fromProject(this) .execute(); }这段代码的核心动作是:
new PmdOperation():创建一个 PMD 操作实例;.fromProject(this):让该操作从当前构建项目(this即当前 bld 项目类)中读取项目信息,例如源码目录、依赖等;.execute():真正执行 PMD 分析。
默认情况下,PmdOperation会对项目源码执行 PMD 检查,使用的是 PMD 内置的 java quickstart rule(快速入门规则集)。如果你想对全部源码执行检查,这就是一个开箱即用的起点。
运行 PMD 检查
声明好pmd()构建命令后,在项目根目录执行以下命令即可运行分析:
./bld pmd test这条命令的含义是:先执行pmd命令(即上一步声明的构建方法),再执行test命令。bld 会按照命令行中命令的先后顺序依次执行,因此./bld pmd test实现了“先做静态分析,再跑测试”的典型质量门禁(quality gate)流程。你也可以单独运行./bld pmd只做静态分析。
了解 PMD 的规则集体系
上面提到的 “java quickstart rule” 是 PMD 内置的 Java 快速入门规则集,其真实配置文件位于仓库的 pmd-java/src/main/resources/rulesets/java/quickstart.xml。该规则集的描述是:“Quickstart configuration of PMD. Includes the rules that are most likely to apply everywhere.”(PMD 的快速入门配置,包含最可能普遍适用的规则)。
从这个配置文件可以看出 PMD 规则集的组成方式:规则通过category/...xml分类规则文件按类别引用,每一行rule ref引用一条具体规则,注释掉的行表示该类别下的规则并未启用。quickstart 规则集主要覆盖以下类别:
- bestpractices(最佳实践):如
AvoidMessageDigestField、AvoidStringBufferField、AvoidUsingHardCodedIP、CheckResultSet、ConstantsInInterface、DoubleBraceInitialization、ForLoopCanBeForeach、GuardLogStatement、MissingOverride、UnusedFormalParameter、UnusedLocalVariable、UnusedPrivateField、UnusedPrivateMethod、UseCollectionIsEmpty、UseStandardCharsets等; - codestyle(代码风格):如
ClassNamingConventions、FormalParameterNamingConventions、LocalVariableNamingConventions、MethodNamingConventions、PackageCase、TypeParameterNamingConventions、AvoidDollarSigns、ControlStatementBraces、ExtendsObject、UnnecessaryImport、UnnecessaryModifier、UselessParentheses等; - design(设计):如
AbstractClassWithoutAnyMethod、ClassWithOnlyPrivateConstructorsShouldBeFinal、FinalFieldCouldBeStatic、InstantiableUtilityClass、LogicInversion、SimplifiedTernary、SimplifyBooleanReturns、SimplifyConditional、SingularField、UselessOverridingMethod等; - documentation(文档):如
DanglingJavadoc、UncommentedEmptyConstructor、UncommentedEmptyMethodBody; - errorprone(易错点):如
AssignmentInOperand、AvoidBranchingStatementAsLastInLoop、AvoidCatchingGenericException、AvoidUsingOctalValues、BrokenNullCheck、CloseResource、CompareObjectsWithEquals、DoNotCallGarbageCollectionExplicitly、EqualsNull、IdempotentOperations、ProperLogger、ReturnFromFinallyBlock、UnconditionalIfStatement等; - multithreading(多线程):如
AvoidThreadGroup、AvoidUsingVolatile、DontCallThreadRun、DoubleCheckedLocking、NonThreadSafeSingleton、UseNotifyAllInsteadOfNotify; - performance(性能):如
BigIntegerInstantiation、OptimizableToArrayCall; - 以及若干 “Empty rules”:
EmptyControlStatement、UnnecessarySemicolon、EmptyCatchBlock、EmptyFinalizer。
此外,quickstart 规则集还展示了两类进阶配置方式:
- 规则属性定制:例如
AssignmentInOperand规则显式配置了allowWhile=true,AvoidCatchingGenericException规则通过typesThatShouldNotBeCaught属性限定仅捕获java.lang.Throwable和java.lang.Error。这说明同一规则可以通过属性调整行为,而不必修改规则本身; - 规则裁剪:大量规则以注释形式存在,方便你按需取消注释来启用,或参考其引用来构建自己的规则集。
自定义规则集并接入 bld
PMD 官方强烈建议从一开始就创建自己的规则集(见 Making rulesets),以便精确控制项目中启用的规则与配置。创建规则集的第一步是使用官方模板:
<?xml version="1.0"?> <ruleset name="Custom 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> My custom rules </description> <!-- Your rules will come here --> </ruleset>你可以在<description>之后通过<rule ref="category/java/...xml/..."/>引用任意规则,例如:
<rule ref="category/java/codestyle.xml/UnnecessaryModifier"/> <rule ref="category/java/bestpractices.xml/MissingOverride"/>也可以整体引用某个规则集文件作为基础。当自定义规则集就绪后,可以将其加入项目的类路径,并在PmdOperation中通过相关配置指向该规则集文件(具体配置方式可参阅 bld-pmd 扩展的文档)。这样,你的 bld 构建就能执行与团队约定一致的静态检查标准。
提升分析深度:辅助类路径(aux classpath)
PMD 对 Java 代码的深度分析依赖类型与符号解析。当被分析的代码引用了项目其他模块或外部依赖中的类型时,PMD 需要知道这些依赖才能正确判断方法重写、类型归属等语义。为此,需要为分析提供完整的辅助类路径(auxiliary classpath,简称 auxClasspath),其配置方式详见 Java 语言支持文档。
关键的配置要点包括:
- auxClasspath 是一个路径字符串,在 Linux/macOS 下用冒号(
:)分隔,Windows 下用分号(;)分隔; - 路径中应包含:被分析项目的编译产物(如
target/classes)、全部编译期依赖,以及正确版本的 Java 运行时类; - Java 9 及以后,Java 运行时类位于
${JAVA_HOME}/lib/modules,需要通过${JAVA_HOME}/lib/jrt-fs.jar提供的jrt://文件系统读取,因此应将jrt-fs.jar作为 auxClasspath 的第一项加入; - Java 8 及以前则使用
${JAVA_HOME}/jre/lib/rt.jar; - 若未显式提供运行时类,PMD 会回退到加载当前运行 PMD 的 JVM 的运行时类。如果你用 Java 8 运行 PMD 却分析 Java 21 的代码,就会得到错误的分析结果,并收到警告
"Adding current platform ... Please add the correct jrt-fs.jar explicitly to the auxClasspath."; - 确认版本无误后,可通过环境变量
PMD_JAVA_DISABLE_AUX_CLASSPATH_WARNINGS=true关闭该警告。
一个正确的 CLI 示例是:
pmd check -d src/main/java \ --aux-classpath=path/to/java17/lib/jrt-fs.jar:target/classes/ \ -f xml -r pmd-report.xml -R rulesets/java/quickstart.xml在 bld 集成场景下,你同样需要将项目的编译输出与依赖正确提供给 PMD。由于 bld 构建逻辑本身就是 Java 代码,你可以方便地计算出项目类路径并传递给PmdOperation,从而实现与 Maven/Gradle 集成中同等深度的类型解析能力。缺少正确的 auxClasspath 可能导致部分规则(如MissingOverride)出现误报或漏报——详见 Java 支持文档 中的具体示例。
将 PMD 检查纳入构建生命周期
./bld pmd test只是串联方式之一。bld 的@BuildCommand方法体系允许你灵活编排任务顺序,常见的实践包括:
- 本地开发门禁:
./bld pmd test确保提交前静态检查与测试全部通过; - CI 流水线集成:在持续集成环境中直接调用
./bld pmd,并将违规报告输出为 CI 可解析的格式; - 增量执行:结合 bld 自身的任务调度,避免重复分析未变更的源码。
关于 PMD 支持的多种报告格式(text、xml、html、json、sarif 等)与命令行参数细节,可参考 PMD CLI Reference 与 PMD Report Formats。这些格式与参数同样适用于通过 bld 扩展驱动的 PMD 分析,帮助你对接不同的质量平台。
参考链接
- 官方文档: bld PMD Extension
- bld 主页与扩展安装说明:https://rife2.com/bld(扩展安装见 bld 的 Extensions 文档)
- PMD 扩展仓库:https://github.com/rife2/bld-pmd
- PMD Java 规则与辅助类路径:Java 支持
- 创建自定义规则集:Making rulesets
- 构建工具集成总览:Tools / Integrations
- 静态分析
- 代码质量
【免费下载链接】pmd
An extensible multilanguage static code analyzer.
相关推荐
Daft 实战:Physical AI 数据集运动裁剪——不解码视频,仅用关节位置列式扫描修剪机器人片段
Daft 实战:Physical AI 数据集运动裁剪——不解码视频,仅用关节位置列式扫描修剪机器人片段 本指南围绕 Daft 生态的 daft physica
静态分析代码质量CoffeeScript Cake 构建系统指南:用 Cakefile 定义并执行任务
CoffeeScript Cake 构建系统指南:用 Cakefile 定义并执行任务 CoffeeScript 自带一套极简的构建系统 Cake,它模仿 Ma
编程语言编译器重新定义人机交互:Mobile-Agent如何让AI成为你的跨平台数字管家
重新定义人机交互:Mobile Agent如何让AI成为你的跨平台数字管家 你是否曾想过,有一天只需对AI说一句话,它就能自动帮你完成手机上所有的繁琐操作?从搜
人工智能大模型AI AgentGUI 自动化自主智能体
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考