SpotBugs 簡介

banq發表於2024-07-17

識別 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的<plugins>部分匯入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 = <font>"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