SpotBugs 简介

识别 Java 程序中的错误是软件开发中的一项关键挑战。SpotBugs是一个开源静态分析工具,用于查找 Java 代码中的错误。它对 Java 字节码而不是源代码进行操作,以识别代码中的潜在问题,例如错误、性能问题或不良做法。SpotBugs 是FindBugs的后继者,并以其功能为基础,提供更详细和精确的错误检测。在本文中,我们将探讨如何在 Java 项目上设置 SpotBugs 并将其集成到 IDE 和 Maven 构建中。 

错误模式
SpotBugs 检查 400 多种错误模式,例如空指针取消引用、无限递归循环、Java 库的错误使用和死锁。在 SpotBugs 中,错误模式通过几个变量进行分类,例如违规类型、类别、错误的等级以及发现过程的可信度。SpotBugs 有十个错误模式类别:

  • 不良做法:检测可能不会立即导致问题但可能导致未来问题的不良编码做法。示例包括哈希码和相等问题、可克隆习语、丢弃异常、可序列化问题以及对finalize的误用。
  • 正确性:识别可能不正确且可能会导致运行时错误(例如可能的错误)的代码。
  • 实验性的:指的是相对较新的、实验性的或尚未完全验证的错误模式。
  • 国际化:检测 Java 代码中与国际化和区域设置相关的潜在问题。
  • 恶意代码漏洞:标记可能被攻击者利用的代码。
  • 多线程正确性:检查多线程代码中的潜在问题,例如竞争条件和死锁。
  • 伪随机噪声:旨在用作数据挖掘实验中的控制,而不是用于查找软件中的实际错误。
  • 性能:识别不一定不正确但可能效率低下的代码。
  • 安全性:突出显示代码中的安全漏洞。
  • 可疑代码:查找不一定错误但可疑且可能有问题的代码。令人困惑、异常或以导致错误的方式编写的代码。示例包括无效的本地存储、切换失败、未经确认的强制类型转换以及已知为空的值的冗余空值检查。
SpotBugs 的一项功能是能够将错误分为不同的严重程度等级。SpotBugs 按 1 到 20 的数字等级对错误进行排名,排名表示问题的严重程度。数字排名可分为以下几类:
  • 最恐怖(高优先级):等级 1 至 4
  • 恐怖(中等优先级):等级 5 至 9
  • 令人不安(低优先级):等级 10 至 14
  • 值得关注(信息性):排名 15 至 20

SpotBugs Maven 插件
Spotbugs 可以作为独立应用程序使用,也可以通过多种集成使用,包括Maven、Gradle、 Eclipse 和 IntelliJ。在本节中,我们将重点介绍 Maven 集成。

Maven 配置
让我们首先在pom.xml的部分导入spotbugs -maven-plugin插件:

<plugin>
    <groupId>com.github.spotbugs</groupId>
    <artifactId>spotbugs-maven-plugin</artifactId>
    <version>4.8.5.0</version>
    <dependencies>
        <dependency>
        <groupId>com.github.spotbugs</groupId>
            <artifactId>spotbugs</artifactId>
        <version>4.8.5</version>
        </dependency>
    </dependencies>
</plugin>

生成报告
添加插件后,我们可以打开终端并运行以下命令:

mvn spotbugs:check

这将对我们的源代码进行分析,然后输出我们需要修复的警告列表。要生成错误报告,我们需要一些代码来处理。为简单起见,我们将使用 GitHub 上提供的项目。假设我们使用以下类:

public class Application {
    public static final String NAME = "Name: ";
    private Application() {
    }
    public static String readName() {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.next();
        return NAME.concat(input);
    }
}

现在,我们可以运行mvn spotbugs:check命令。运行该命令时检测到以下内容:

[INFO] BugInstance size is 1
[INFO] Error size is 0
[INFO] Total bugs: 1
[ERROR] High: Found reliance on default encoding in com.baeldung.systemin.Application.readName(): new java.util.Scanner(InputStream) [com.baeldung.systemin.Application] At Application.java:[line 13] DM_DEFAULT_ENCODING

从该报告中,我们可以看到我们的Application类有一个高优先级的错误。

查看结果
SpotBugs 在target/spotbugsXml.xml中生成 XML 格式的报告。为了获得更漂亮的报告,我们需要在 SpotBugs 插件中添加htmlOutput配置:

<configuration>
    <htmlOutput>true</htmlOutput>
</configuration>

现在,我们运行mvn clean install和mvn spotbugs:check命令。然后,我们导航到target/spotbugs.html 并打开文件以直接在浏览器中查看结果:   此外,我们可以使用 Maven 命令mvn spotbugs:gui使用 Spotbugs GUI 查看错误详细信息:   有了此反馈,我们现在可以更新代码以主动修复错误。

修复错误
我们的Application类有DM_DEFAULT_ENCODING错误。该错误表示在执行 I/O 操作时使用了默认字符编码。如果默认编码在不同环境或平台上有所不同,这可能会导致意外行为。通过明确指定字符编码,我们可以确保无论平台的默认编码如何,行为都是一致的。为了解决这个问题,我们可以将StandardCharsets添加到Scanner类:

public static String readName() {
    Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8.displayName());
    String input = scanner.next();
    return NAME.concat(input);
}

添加之前建议的更改后,再次运行mvn spotbugs:check将生成无错误的报告:

[INFO] BugInstance size is 0
[INFO] Error size is 0
[INFO] No errors/warnings found