SpotBugs

← 返回目录 > ← 返回总览

相关工具推荐

1. 简介

SpotBugs 是 FindBugs 的官方继任者(FindBugs 已停止维护),是一款开源的 Java 静态代码分析工具。它通过分析编译后的 Java 字节码(.class 文件)来检测代码中超过 400 种已知的 Bug 模式,包括空指针异常、资源泄漏、线程安全问题、安全漏洞和不良编码实践等。

  • 主要检查语言:Java(字节码分析)
  • 主要检查能力:检测 Java 字节码中的空指针、并发问题、性能缺陷、不良实践等已知 Bug 模式;涵盖质量类检查(潜在 Bug 模式检测)
  • 核心检查原理:字节码级分析,不依赖源代码
  • 检查规则/选项:400+ 个标准 Bug Pattern(分布在 BAD_PRACTICE、CORRECTNESS、PERFORMANCE、SECURITY、STYLE 等 10 个大类),全量 Bug Pattern 列表
  • GitHub 仓库https://github.com/spotbugs/spotbugs(3,895 stars)
  • 开源协议:LGPL-2.1-or-later
  • 最新稳定版本:v4.9.3
  • 运行环境要求:需 JRE 11+(v4.8+ 起);通过 Maven/Gradle 插件集成
  • 误报率:中

2. 官方文档

资源 链接 说明
官方网站 https://spotbugs.github.io/ 项目主页,包含概览和快速入口
官方手册(ReadTheDocs) https://spotbugs.readthedocs.io/en/latest/ 完整使用手册,涵盖安装、配置、集成等
Bug 描述文档 https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html 全部 400+ Bug 模式的详细描述
Bug 描述(日文版) https://spotbugs.readthedocs.io/ja/latest/bugDescriptions.html 日文版 Bug 描述
GitHub 仓库 https://github.com/spotbugs/spotbugs 源代码、Issue 追踪、Release 下载
GitHub Releases https://github.com/spotbugs/spotbugs/releases 版本发布记录与下载
Maven 插件文档 https://spotbugs.readthedocs.io/en/latest/maven.html spotbugs-maven-plugin 配置说明
Maven 插件站点 https://spotbugs.github.io/spotbugs-maven-plugin/ Maven 插件完整参数文档(spotbugs goal、check goal)
Gradle 插件文档 https://spotbugs.readthedocs.io/en/latest/gradle.html spotbugs-gradle-plugin 配置说明
Gradle Plugin Portal https://plugins.gradle.org/plugin/com.github.spotbugs Gradle 插件版本与安装说明
Filter 配置文档 https://spotbugs.readthedocs.io/en/latest/filter.html Include/Exclude Filter XML 语法说明
命令行选项文档 https://spotbugs.readthedocs.io/en/latest/running.html 命令行参数完整说明
Effort 文档 https://spotbugs.readthedocs.io/en/latest/effort.html 分析深度级别详细说明
Annotations 文档 https://spotbugs.readthedocs.io/en/latest/annotations.html SpotBugs 注解完整说明
API 文档(Javadoc) https://javadoc.io/doc/com.github.spotbugs/spotbugs/ SpotBugs API Javadoc
Eclipse 插件 https://marketplace.eclipse.org/content/spotbugs-eclipse-plugin Eclipse Marketplace 插件页
IntelliJ 插件 https://github.com/JetBrains/spotbugs-intellij-plugin JetBrains 官方维护的 IntelliJ SpotBugs 插件
VS Code 插件 https://github.com/shblue21/vscode-spotbugs VS Code SpotBugs 扩展
fb-contrib 插件 https://github.com/mebigfatguy/fb-contrib 第三方扩展检测器插件
find-sec-bugs 插件 https://find-sec-bugs.github.io/ 安全漏洞检测插件

3. 社区优秀实践

3.1 Apache 基金会项目

Apache 基金会多个顶级项目使用 SpotBugs 作为 Java 代码质量保障工具,通常在 pom.xml 中集成 spotbugs-maven-plugin 并配合自定义 Filter 文件。

典型实践:在 verify 阶段自动执行 spotbugs:check,配合 exclude filter 排除自动生成代码和测试类。

3.2 Jenkins 社区

Jenkins 是 SpotBugs 的重要使用者,不仅自身代码使用 SpotBugs 检查,还通过 Jenkins SpotBugs Plugin 发布分析报告和趋势图。

典型实践:在 Jenkins Pipeline 中集成 SpotBugs 扫描,通过 SpotBugs Plugin 可视化展示分析结果,支持历史趋势追踪和构建失败阈值设置。

3.3 SonarQube / SonarSource

SonarQube 内置集成了 SpotBugs 作为 Java 代码的 Bug 检测引擎,在 SonarQube 的 Java 分析器中直接调用 SpotBugs 进行字节码分析。

典型实践:SonarQube 将 SpotBugs 的检测结果统一纳入其质量门禁(Quality Gate)体系,与其他规则(如自定义规则、PMD 规则)一起进行综合评估。


4. 工具配置说明

4.1 配置文件说明

SpotBugs 涉及以下配置文件:

配置文件 用途 使用场景
spotbugs-include.xml(Include Filter) 包含过滤器,指定只检查匹配的类或 Bug 模式 需要聚焦特定包/类别/Bug 模式的项目
spotbugs-exclude.xml(Exclude Filter) 排除过滤器,排除不需要检查的类或 Bug 模式 需要排除自动生成代码、测试类、特定 Bug 模式的项目

Effort 与 Threshold 配置(分析参数,可通过命令行或 Maven/Gradle 插件指定):

参数 可选值 说明
effort min 最小分析深度,跳过部分分析,速度最快
default / more 默认分析深度,平衡速度与检测量
max 最大分析深度,启用所有分析,检测最全面
threshold high(对应 Confidence High) 只报告高置信度的 Bug
medium(对应 Confidence Medium) 报告高和中置信度的 Bug(默认)
low(对应 Confidence Low) 报告所有置信度的 Bug
exp 报告实验性 Bug 模式

参考文档Filter 文件完整说明Effort 详细说明

4.2 Filter 配置详解

SpotBugs 的 Include Filter 与 Exclude Filter 均采用 FindBugsFilter XML 格式,通过 <Match> 及其子元素描述匹配条件。

配置项说明(Filter 匹配元素):

元素 类型 说明 示例
<Match> 容器 匹配条件容器(子元素为 AND 关系) -
<Class> 元素 按类名匹配(支持正则,~ 开头) <Class name="~com\.example\..*"/>
<Package> 元素 按包名匹配 <Package name="com.example.service"/>
<Source> 元素 按源文件名匹配 <Source name="~.*\.groovy"/>
<Method> 元素 按方法名/签名匹配 <Method name="toString"/>
<Field> 元素 按字段名匹配 <Field name="~.*password.*"/>
<Bug pattern> 元素 按 Bug 模式精确匹配 <Bug pattern="NP_NULL_ON_SOME_PATH"/>
<Bug code> 元素 按 Bug 代码前缀匹配 <Bug code="NP"/>
<Bug category> 元素 按 Bug 类别匹配 <Bug category="SECURITY"/>
<Confidence> 元素 按置信度匹配(1=高,2=中,3=低) <Confidence value="1"/>
<Rank> 元素 按 Bug 严重程度匹配(1-20) <Rank value="9"/>
<Or> 容器 逻辑或 组合多个条件
<And> 容器 逻辑与 组合多个条件
<Not> 容器 逻辑非 取反条件

推荐配置示例

Include Filterspotbugs-include.xml,聚焦于高价值 Bug 模式,适合大多数 Java 项目):

<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>

    <!-- ===== 正确性(CORRECTNESS)===== -->
    <Match>
        <Bug pattern="NP_NULL_ON_SOME_PATH"/>
    </Match>
    <Match>
        <Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
    </Match>
    <Match>
        <Bug pattern="NP_NULL_PARAM_DEREF"/>
    </Match>

    <!-- ===== 多线程正确性(MT_CORRECTNESS)===== -->
    <Match>
        <Bug pattern="LI_LAZY_INIT_STATIC"/>
    </Match>
    <Match>
        <Bug pattern="DC_DOUBLECHECK"/>
    </Match>
    <Match>
        <Bug pattern="IS2_INCONSISTENT_SYNC"/>
    </Match>

    <!-- ===== 安全(SECURITY)===== -->
    <Match>
        <Bug pattern="SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING"/>
    </Match>

    <!-- ===== 不良实践(BAD_PRACTICE)===== -->
    <Match>
        <Bug pattern="OS_OPEN_STREAM"/>
    </Match>
    <Match>
        <Bug pattern="OS_OPEN_STREAM_EXCEPTION_PATH"/>
    </Match>
    <Match>
        <Bug pattern="RV_RETURN_VALUE_IGNORED"/>
    </Match>
    <Match>
        <Bug pattern="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE"/>
    </Match>
    <Match>
        <Bug pattern="HE_EQUALS_USE_HASHCODE"/>
    </Match>
    <Match>
        <Bug pattern="HE_HASHCODE_NO_EQUALS"/>
    </Match>
    <Match>
        <Bug pattern="EI_EXPOSE_REP"/>
    </Match>
    <Match>
        <Bug pattern="EI_EXPOSE_REP2"/>
    </Match>
    <Match>
        <Bug pattern="MS_EXPOSE_REP"/>
    </Match>
    <Match>
        <Bug pattern="REC_CATCH_EXCEPTION"/>
    </Match>
    <Match>
        <Bug pattern="DE_MIGHT_IGNORE"/>
    </Match>
    <Match>
        <Bug pattern="ES_COMPARING_STRINGS_WITH_EQ"/>
    </Match>

    <!-- ===== 性能(PERFORMANCE)===== -->
    <Match>
        <Bug pattern="DM_DEFAULT_ENCODING"/>
    </Match>
    <Match>
        <Bug pattern="DM_NUMBER_CTOR"/>
    </Match>
</FindBugsFilter>

Exclude Filterspotbugs-exclude.xml,排除自动生成代码、测试类、噪音类别):

<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>

    <!-- 排除自动生成的代码 -->
    <Match>
        <Class name="~.*\.generated\..*"/>
    </Match>
    <Match>
        <Class name="~.*_generated"/>
    </Match>

    <!-- 排除测试类 -->
    <Match>
        <Class name="~.*Test"/>
    </Match>
    <Match>
        <Class name="~.*IT$"/>
    </Match>

    <!-- 排除 Builder / DTO / Model / Entity 类 -->
    <Match>
        <Class name="~.*Builder"/>
    </Match>
    <Match>
        <Class name="~.*DTO"/>
    </Match>
    <Match>
        <Class name="~.*Model"/>
    </Match>
    <Match>
        <Class name="~.*Entity"/>
    </Match>

    <!-- 排除噪音类别 -->
    <Match>
        <Bug category="NOISE"/>
    </Match>

    <!-- 排除实验性 Bug 模式 -->
    <Match>
        <Bug category="EXPERIMENTAL"/>
    </Match>
</FindBugsFilter>

Maven/Gradle 插件中通过 includeFilterFileexcludeFilterFile 参数引用上述过滤器文件,具体集成配置见第 5 章。

4.3 Bug 类别说明

SpotBugs 的 400+ Bug 模式分为以下类别:

类别 标识 说明 建议处理方式
恶意代码漏洞 MALICIOUS_CODE 可能被不受信任代码攻击的漏洞 必须修复
多线程正确性 MT_CORRECTNESS 线程、锁、volatile 相关缺陷 必须修复
安全 SECURITY 可能导致远程利用的安全漏洞 必须修复
正确性 CORRECTNESS 可能的编码错误 建议修复
不良实践 BAD_PRACTICE 违反推荐编码实践 建议修复
性能 PERFORMANCE 代码效率低下但不一定错误 视情况修复
国际化 I18N 国际化和区域设置相关缺陷 视需求修复
糟糕代码 STYLE 代码混乱、容易导致错误 可选修复
实验性 EXPERIMENTAL 实验性 Bug 模式 可选修复

完整 Bug 模式列表请参考:Bug descriptions

4.4 核心 Bug Detectors 列表

以下是 SpotBugs 最常用的检测器及其检测的 Bug 模式:

检测器 Bug 模式 类别 说明
FindNullDereference NP_NULL_ON_SOME_PATH CORRECTNESS 检测可能的空指针解引用
NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE CORRECTNESS 方法返回值可能为 null,调用者未检查
NP_NULL_PARAM_DEREF CORRECTNESS 方法参数可能为 null,内部未检查
FindOpenStream OS_OPEN_STREAM BAD_PRACTICE 流资源未关闭
OS_OPEN_STREAM_EXCEPTION_PATH BAD_PRACTICE 异常路径上流资源未关闭
FindReturnRef EI_EXPOSE_REP MALICIOUS_CODE 方法返回内部可变引用
EI_EXPOSE_REP2 MALICIOUS_CODE 方法参数存储到字段,暴露内部状态
MS_EXPOSE_REP MALICIOUS_CODE public 方法返回可变内部字段
FindInconsistentSync IS2_INCONSISTENT_SYNC MT_CORRECTNESS 不一致的同步
FindDoubleCheck DC_DOUBLECHECK MT_CORRECTNESS 双检锁模式不正确
FindLazyInit LI_LAZY_INIT_STATIC MT_CORRECTNESS 静态字段非同步懒初始化
FindSqlInjection SQL_INJECTION_JDBC SECURITY SQL 注入漏洞
FindHEmismatch HE_EQUALS_USE_HASHCODE BAD_PRACTICE equals 方法使用了 hashCode
HE_HASHCODE_NO_EQUALS BAD_PRACTICE 定义了 hashCode 但未定义 equals
DroppedException DE_MIGHT_IGNORE BAD_PRACTICE 可能忽略了异常
DefaultEncodingDetector DM_DEFAULT_ENCODING PERFORMANCE 使用平台默认编码
InefficientStringBuffering SBSC_USE_STRINGBUFFER_CONSTRUCTOR PERFORMANCE 低效的字符串拼接
FindNonShortCircuit NS_NON_SHORT_CIRCUIT BAD_PRACTICE 使用 & 或 | 代替 && 或 ||

完整检测器列表请参考:Detectors

4.5 Confidence 级别说明

SpotBugs 的每个 Bug 报告都有一个 Confidence 级别,表示该检测的置信度:

Confidence 对应 threshold 说明
High threshold=High 高置信度,几乎确定是真实 Bug
Medium threshold=Medium 中置信度,很可能是 Bug,但有一定误报可能
Low threshold=Low 低置信度,可能是 Bug,误报率较高
Experimental threshold=Exp 实验性检测,仅供参考

推荐策略

  • CI/CD 流水线:使用 threshold=Medium,只阻断中高置信度的 Bug
  • 本地开发:使用 threshold=Low,尽可能多地发现问题
  • 新项目首次引入:先用 threshold=High 建立基线,逐步降低阈值

4.6 Bug 优先级(Rank)说明

SpotBugs 使用 1-20 的数值排名表示 Bug 的严重程度:

排名范围 优先级 说明
1-4 Scariest(最高) 最严重的 Bug,必须立即修复
5-9 Scary(高) 严重的 Bug,应尽快修复
10-14 Troubling(中) 中等严重,应在迭代内修复
15-20 Of Concern(低) 较低严重,可酌情处理

5. 主流集成方式

5.1 Maven 集成(生态主流,优先)

pom.xml 中添加 spotbugs-maven-plugin(最新版本 4.10.2.0):

<project>
    <build>
        <plugins>
            <plugin>
                <groupId>com.github.spotbugs</groupId>
                <artifactId>spotbugs-maven-plugin</artifactId>
                <version>4.10.2.0</version>
                <dependencies>
                    <!-- 指定 SpotBugs 核心版本 -->
                    <dependency>
                        <groupId>com.github.spotbugs</groupId>
                        <artifactId>spotbugs</artifactId>
                        <version>4.10.2</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <effort>Max</effort>
                    <threshold>Low</threshold>
                    <xmlOutput>true</xmlOutput>
                    <htmlOutput>true</htmlOutput>
                    <failOnError>true</failOnError>
                    <excludeFilterFile>spotbugs-exclude.xml</excludeFilterFile>
                    <includeFilterFile>spotbugs-include.xml</includeFilterFile>
                    <plugins>
                        <!-- 可选:添加 find-sec-bugs 安全检测插件 -->
                        <plugin>
                            <groupId>com.h3xstream.findsecbugs</groupId>
                            <artifactId>findsecbugs-plugin</artifactId>
                            <version>1.14.0</version>
                        </plugin>
                        <!-- 可选:添加 sb-contrib 扩展检测器 -->
                        <plugin>
                            <groupId>com.mebigfatguy.sb-contrib</groupId>
                            <artifactId>sb-contrib</artifactId>
                            <version>7.7.4</version>
                        </plugin>
                    </plugins>
                </configuration>
                <executions>
                    <execution>
                        <phase>verify</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

常用 Maven 命令

# 生成报告(不阻断构建)
mvn spotbugs:spotbugs

# 检查并阻断构建(发现 Bug 则构建失败)
mvn spotbugs:check

# 打开 GUI 查看结果
mvn spotbugs:gui

# 查看插件帮助
mvn spotbugs:help -Ddetail=true

参考文档Maven 插件文档 | Maven 插件站点(完整参数)

增量检查:Maven 支持增量编译,只有变更的源文件才会被重新编译为 .class 文件。结合构建工具的增量编译能力,SpotBugs 可以只分析已编译的 .class 文件:

# Maven:增量编译后只分析变更的类
mvn compile spotbugs:check

通过 onlyAnalyze 参数限制分析范围到特定包或类,实现局部增量分析:

<configuration>
    <onlyAnalyze>com.example.app.*</onlyAnalyze>
</configuration>

或通过命令行:

mvn spotbugs:check -Dspotbugs.onlyAnalyze="com.example.app.*"

5.2 pre-commit 集成

SpotBugs 需要编译后的 .class 文件,pre-commit hook 依赖本地 JDK 和构建工具链。

注意:以下配置使用 language: system,依赖本地已安装的 JDK 和 Maven/Gradle,执行环境需要预先完成项目编译。

repos:
  - repo: local
    hooks:
      - id: spotbugs
        name: SpotBugs Static Analysis
        entry: mvn spotbugs:check -q -Dmaven.test.skip=true
        language: system
        files: \.java$
        pass_filenames: false

安装钩子:

pip install pre-commit
pre-commit install

说明pass_filenames: false 表示不将变更文件列表传给 hook,因为 SpotBugs 需要分析编译后的完整 class 文件。language: system 要求本地环境已安装 JDK 和 Maven。

增量检查:SpotBugs 是字节码级分析工具,需要先编译 Java 源码生成 .class 文件才能分析,不适合放入 pre-commit 提交前检查。建议在本地手动运行 mvn compile spotbugs:check 或在 PR 门禁中执行。参见 Java 语言指南 中关于 SpotBugs 不放入 pre-commit 的说明。

5.3 IDE 集成

IntelliJ IDEA

JetBrains 官方维护了 SpotBugs IntelliJ 插件

  1. 打开 File -> Settings -> Plugins
  2. 搜索 "SpotBugs" 并安装
  3. 安装后右键项目 -> SpotBugs -> Analyze Project Files
  4. 分析结果会在 SpotBugs Tool Window 中展示,支持按严重级别过滤

也可以通过 Maven/Gradle 插件间接使用:在 IDEA 的 Maven/Gradle 工具窗口中双击 spotbugs:check 任务即可运行。

Eclipse

  1. 打开 Help -> Eclipse Marketplace
  2. 搜索 "SpotBugs Eclipse Plugin" 并安装
  3. 右键项目 -> SpotBugs -> Find Bugs
  4. 分析结果会在 SpotBugs Explorer 视图中展示

可通过 m2e-code-quality 插件自动从 Maven 配置同步 SpotBugs 设置到 Eclipse。

VS Code

SpotBugs for VS Code 扩展支持在 VS Code 中直接运行 SpotBugs 分析:

  1. 在 VS Code 扩展市场搜索 "SpotBugs" 并安装
  2. 要求安装 "Language Support for Java by Red Hat" 扩展
  3. 使用命令面板运行 "SpotBugs: Analyze this workspace""SpotBugs: Analyze File/Folder"
  4. 分析结果在 "SpotBugs" 视图中展示,支持导出 SARIF 报告

5.4 命令行使用方式

下载安装

从 GitHub Releases 下载最新版本:

# 下载
wget https://github.com/spotbugs/spotbugs/releases/download/4.10.2/spotbugs-4.10.2.tgz

# 解压
tar -xzf spotbugs-4.10.2.tgz -C /opt/

# 配置环境变量
export SPOTBUGS_HOME=/opt/spotbugs-4.10.2
export PATH=$PATH:$SPOTBUGS_HOME/bin

基本命令

# 查看版本
spotbugs -version

# 文本模式分析 JAR 文件
spotbugs -textui -effort:max -high -medium -low \
    -exclude spotbugs-exclude.xml \
    ./target/myapp.jar

# 生成 HTML 报告
spotbugs -textui -html -outputFile report.html \
    -effort:max \
    ./target/classes

# 生成 XML 报告
spotbugs -textui -xml -outputFile report.xml \
    ./target/classes

# 生成 SARIF 报告(用于 GitHub Code Scanning)
spotbugs -textui -sarif -outputFile report.sarif.json \
    ./target/classes

# 启动 GUI 查看结果
spotbugs -gui ./target/classes

通过 JAR 直接运行

java -Xmx2048m -jar $SPOTBUGS_HOME/lib/spotbugs.jar \
    -textui \
    -effort:max \
    -high -medium -low \
    -exclude spotbugs-exclude.xml \
    ./target/myapp.jar

命令行参数说明

参数 说明
-textui 命令行文本模式
-gui 图形界面模式
-version 显示版本号
-help 显示帮助信息
-effort:min|default|more|max 分析深度
-high / -medium / -low 报告的优先级范围
-xml=path/to/file 输出 XML 格式报告
-html=path/to/file 输出 HTML 格式报告
-sarif=path/to/file 输出 SARIF 格式报告
-exclude <filter.xml> 排除过滤器文件
-include <filter.xml> 包含过滤器文件
-onlyAnalyze <classes> 限制分析范围到指定类/包
-maxHeap <size> JVM 最大堆内存(MB)
-pluginList <jars> 指定插件 JAR 列表
-visitors <v1,v2> 只运行指定检测器
-omitVisitors <v1,v2> 禁用指定检测器
-chooseVisitors <+v1,-v2> 选择性启用/禁用检测器
-maxRank <rank> 只报告优先级 <= 指定值的 Bug
-bugCategories <cat1,cat2> 只报告指定类别的 Bug

参考文档命令行选项

增量检查:通过 git diff 获取变更的 Java 文件列表,编译后只分析对应的 class 文件:

# 获取变更的 Java 文件并编译
CHANGED_FILES=$(git diff --name-only --diff-filter=ACMR HEAD | grep '\.java$')
mvn compile

# 将变更的 .java 文件转换为 .class 文件路径,配合 onlyAnalyze 使用
# 注意:SpotBugs 的 onlyAnalyze 接受的是类全限定名而非文件路径
CLASSES=$(echo "$CHANGED_FILES" | sed 's|src/main/java/||;s|\.java$||;s|/|.|g')
spotbugs -textui -onlyAnalyze "$CLASSES" ./target/classes

CI 脚本调用:在 CI 环境中通过脚本调用 SpotBugs 进行静态分析。

GitHub Actions

name: SpotBugs Analysis

on: [push, pull_request]

jobs:
  spotbugs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: "17"
          distribution: "temurin"

      - name: Cache Maven packages
        uses: actions/cache@v4
        with:
          path: ~/.m2
          key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
          restore-keys: ${{ runner.os }}-m2

      - name: Run SpotBugs
        run: mvn spotbugs:spotbugs

      - name: Upload SpotBugs Report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: spotbugs-report
          path: target/spotbugs.html

GitLab CI

stages:
  - test

spotbugs:
  stage: test
  image: maven:3.9-eclipse-temurin-17
  script:
    - mvn spotbugs:spotbugs
  artifacts:
    when: always
    paths:
      - target/spotbugs.html
      - target/spotbugsXml.xml
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Jenkins Pipeline

pipeline {
    agent any
    tools {
        maven 'Maven 3.9'
        jdk 'JDK 17'
    }
    stages {
        stage('SpotBugs') {
            steps {
                sh 'mvn spotbugs:spotbugs'
            }
            post {
                always {
                    recordIssues(
                        tool: spotBugs(pattern: 'target/spotbugsXml.xml'),
                        qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]
                    )
                }
            }
        }
    }
}

增量检查:GitHub Actions 中按 PR 变更文件触发增量检查:

name: Incremental SpotBugs
on:
  pull_request:
    paths:
      - "src/main/java/**/*.java"
jobs:
  spotbugs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: "17"
          distribution: "temurin"
      - name: Run SpotBugs
        run: mvn spotbugs:check

GitLab CI 中按变更路径触发增量检查:

spotbugs:
  stage: test
  image: maven:3.9-eclipse-temurin-17
  script:
    - mvn spotbugs:check
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      changes:
        - src/main/java/**/*.java
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

5.5 Gradle 集成

使用官方 Gradle 插件(最新版本 6.5.6,默认集成 SpotBugs 4.10.2):

plugins {
    id 'java'
    id 'com.github.spotbugs' version '6.5.6'
}

spotbugs {
    toolVersion = '4.10.2'
    effort = 'max'       // 分析深度:min | default | max
    reportLevel = 'low'  // 报告级别:high | medium | low(对应 confidence)
    ignoreFailures = false
    showProgress = true
    excludeFilter = file('config/spotbugs/exclude.xml')
    includeFilter = file('config/spotbugs/include.xml')
    maxHeapSize = '1g'
}

// 可选:添加扩展插件
dependencies {
    spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.14.0'
    spotbugsPlugins 'com.mebigfatguy.sb-contrib:sb-contrib:7.7.4'
}

spotbugsMain {
    reports {
        xml.required = true
        html.required = true
        html.stylesheet = 'fancy-hist.xsl'
    }
}

Kotlin DSL 写法:

import com.github.spotbugs.snom.Confidence
import com.github.spotbugs.snom.Effort

spotbugs {
    ignoreFailures = false
    showProgress = true
    effort = Effort.DEFAULT
    reportLevel = Confidence.DEFAULT
    excludeFilter = file("exclude.xml")
    includeFilter = file("include.xml")
    maxHeapSize = "1g"
}

常用 Gradle 命令

# 检查主源码
./gradlew spotbugsMain

# 检查测试源码
./gradlew spotbugsTest

# 检查所有源码(./gradlew check 会自动触发)
./gradlew spotbugs

参考文档Gradle 插件文档 | Gradle Plugin Portal | Gradle 插件 README

增量检查:Gradle 自动处理增量编译,只有变更的源文件才会被重新编译。结合 Gradle 的增量编译能力,SpotBugs 可以只分析已编译的 .class 文件:

# Gradle:增量编译 + SpotBugs 任务(Gradle 自动处理增量编译)
./gradlew spotbugsMain

通过 onlyAnalyze 配置限制分析范围到特定包或类:

spotbugs {
    onlyAnalyze = ['com.example.app.*']
}

5.6 Ant 集成

SpotBugs 提供原生 Ant 任务支持:

<taskdef
    name="spotbugs"
    classname="edu.umd.cs.findbugs.anttask.FindBugsTask"
    classpath="${spotbugs.home}/lib/spotbugs-ant.jar"/>

<target name="spotbugs" depends="compile">
    <spotbugs
        home="${spotbugs.home}"
        output="html"
        outputFile="${basedir}/spotbugs-report.html"
        effort="max"
        threshold="low"
        excludeFilter="${basedir}/spotbugs-exclude.xml">
        <class location="${basedir}/build/classes"/>
        <auxClasspath path="${basedir}/lib"/>
        <sourcePath path="${basedir}/src/main/java"/>
    </spotbugs>
</target>

参考文档Ant 任务文档


6. 告警抑制(屏蔽)方法

6.1 通过代码注解屏蔽:@SuppressFBWarnings

在 Java 代码中使用 @SuppressFBWarnings 注解抑制特定告警,需要添加 spotbugs-annotations 依赖:

Maven 依赖

<dependency>
    <groupId>com.github.spotbugs</groupId>
    <artifactId>spotbugs-annotations</artifactId>
    <version>4.10.2</version>
    <optional>true</optional>
</dependency>

Gradle 依赖

compileOnly 'com.github.spotbugs:spotbugs-annotations:4.10.2'

使用方式

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

// 方法级抑制
@SuppressFBWarnings(
    value = "DM_DEFAULT_ENCODING",
    justification = "Output is for local terminal display only, UTF-8 is guaranteed"
)
public void printOutput(String text) {
    System.out.println(text);
}

// 字段级抑制
@SuppressFBWarnings("URF_UNREAD_FIELD")
private int debugCounter;

// 类级抑制(抑制多种 Bug 模式)
@SuppressFBWarnings({
    "EI_EXPOSE_REP2",
    "MS_EXPOSE_REP"
})
public class Configuration {
    private Date configDate;
    // ...
}

// 参数级抑制
public void process(@SuppressFBWarnings("NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE") String input) {
    // ...
}

注意:SpotBugs 不能使用 Java 标准的 @SuppressWarnings 注解,因为它是源代码级注解(RetentionPolicy.SOURCE),在字节码中不可见。必须使用 SpotBugs 专用的 @SuppressFBWarningsRetentionPolicy.CLASS)。

参考文档Annotations 文档 - @SuppressFBWarnings

6.2 通过 Filter 文件屏蔽(项目级)

通过 XML 过滤器文件全局排除特定告警,适用于无法修改源代码的场景(如第三方库、自动生成的代码):

<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
    <!-- 排除特定 Bug 模式 -->
    <Match>
        <Bug pattern="DM_DEFAULT_ENCODING"/>
    </Match>

    <!-- 排除特定包中的所有 Bug -->
    <Match>
        <Package name="com.example.generated"/>
    </Match>

    <!-- 排除特定类中的特定 Bug -->
    <Match>
        <Class name="com.example.legacy.LegacyService"/>
        <Bug pattern="REC_CATCH_EXCEPTION"/>
    </Match>

    <!-- 排除 Groovy 生成代码 -->
    <Match>
        <Source name="~.*\.groovy"/>
    </Match>
</FindBugsFilter>

Maven 中引用

<configuration>
    <excludeFilterFile>spotbugs-exclude.xml</excludeFilterFile>
</configuration>

Gradle 中引用

spotbugs {
    excludeFilter = file('spotbugs-exclude.xml')
}

命令行引用

spotbugs -textui -exclude spotbugs-exclude.xml ./target/classes

参考文档Filter 文件说明 | Filter 文件示例

6.3 通过 Maven/Gradle 配置屏蔽

Maven 排除特定类

通过 onlyAnalyze 参数限制分析范围,间接排除不需要分析的类:

<configuration>
    <onlyAnalyze>com.example.app.*,-com.example.app.generated.*</onlyAnalyze>
</configuration>

Maven excludeBugsFile(按 Bug 实例排除)

excludeBugsFile 用于排除特定的 Bug 实例(基于 Bug Instance 的唯一标识):

<configuration>
    <excludeBugsFile>spotbugs-exclude-bugs.xml</excludeBugsFile>
</configuration>

Gradle 配置屏蔽

spotbugs {
    // 限制分析范围
    onlyAnalyze = ['com.example.app.*']
    // 排除过滤器
    excludeFilter = file('exclude.xml')
    // 包含过滤器
    includeFilter = file('include.xml')
    // 基线文件(排除已知的 Bug)
    baselineFile = file('baseline.xml')
}

参考文档Maven 插件参数 | Gradle 插件扩展配置

6.4 通过命令行参数屏蔽

# 排除特定检测器
spotbugs -textui -omitVisitors FindNonShortCircuit,FindNullDereferences ./target/classes

# 选择性启用/禁用检测器
spotbugs -textui -chooseVisitors "-FindNonShortCircuit,+TestASM" ./target/classes

# 只报告特定类别的 Bug
spotbugs -textui -bugCategories CORRECTNESS,SECURITY ./target/classes

# 只报告高优先级 Bug(maxRank)
spotbugs -textui -maxRank 9 ./target/classes

# 排除基线中已存在的 Bug
spotbugs -textui -excludeBugs baseline.xml ./target/classes

参考文档命令行选项 - 输出过滤选项 | 命令行选项 - 检测器配置选项

6.5 通过 @Nonnull / @CheckForNull 注解辅助减少误报

通过添加空值注解帮助 SpotBugs 更精确地理解代码意图,减少误报:

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.CheckReturnValue;

public class UserService {

    // 标记返回值不为 null
    @NonNull
    public User findUserById(long id) {
        return userRepository.findById(id);
    }

    // 标记返回值可能为 null
    @CheckForNull
    public User findOptionalUser(long id) {
        return userRepository.findByIdOrNull(id);
    }

    // 标记返回值必须被使用
    @CheckReturnValue
    public boolean validate(String input) {
        return input != null && !input.isEmpty();
    }
}

参考文档Annotations 文档

6.6 告警抑制方法总结

方法 粒度 适用场景 是否需要修改代码 官方文档
@SuppressFBWarnings 方法/字段/类/参数 已确认的误报或可接受的例外 Annotations
Exclude Filter 文件 项目/包/类/Bug 模式 第三方代码、生成代码、批量排除 Filter file
Exclude Bugs File Bug 实例 排除特定已知 Bug 实例 Maven 插件参数
@Nonnull/@CheckForNull 方法/参数/字段 辅助减少空指针误报 Annotations
-omitVisitors 检测器级别 禁用特定检测器 命令行选项
-maxRank / threshold 优先级级别 屏蔽低优先级告警 命令行选项
Maven onlyAnalyze 包/类级别 限制分析范围 Maven 插件参数
Gradle baselineFile Bug 实例 排除基线中已存在的 Bug Gradle 扩展配置

← 返回目录 > ← 返回总览