本ページはプロモーションが含まれています

Java入門

SpotBugsの使い方|FindBugsからの移行手順

CATEGORY
REV.
DRAWN BY
TOM
SHEETS
10枚
SpotBugs(FindBugsからの移行)

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

FindBugsの代わりを探しているなら、選ぶべきはSpotBugsです。MavenでもGradleでも、数行の設定を足すだけで動かせます。

FindBugsは2015年の 3.0.1 を最後に開発が止まっており、Java 9以降では動作しません。

SpotBugsはFindBugsから分岐した正統な後継プロジェクトで、解析エンジンや警告パターンもほぼ引き継いでいます。

設定例は、2026年9月時点のSpotBugs 4.10.4 / Mavenプラグイン4.10.4.1 / Gradleプラグイン6.5.11をもとにしています。コピペから始めれば、最短10分で「最初の警告」を出せます。扱う内容は次の4つです。

  • FindBugsとSpotBugsの関係(結論:FindBugsの後継ならSpotBugs一択)
  • Maven / Gradle / Eclipse / IntelliJ IDEAへの導入手順(コピペで動く設定例つき)
  • 主要警告(NP_NULL_ON_SOME_PATH / EI_EXPOSE_REP / OS_OPEN_STREAMなど)の読み方と対処
  • CI(GitHub Actions)・SonarQubeへの組み込み運用パターン

私はJava歴12年で、SpotBugsを使っていた時期もあります。初回スキャンで警告が大量に出たとき、どこから手を付けるかの進め方も載せています。

なお、私自身は現在、JetBrainsのQodanaに乗り換えています。だからこそ「それでもSpotBugsを入れる価値がある場面」を正直に書きます。

PARTS LIST /目次

SpotBugsとは?静的解析で何がわかるか

SpotBugsとは、Javaのバイトコード(.classファイル)を解析し、バグを誘発しやすいパターンを自動検出する静的解析ツールです。

Javaの開発現場で、テストコードだけでは拾いきれない「潜在的な不具合」を見つけ出してくれます。

かつては「FindBugs」という名前で親しまれていましたが、現在はその意志を継いだSpotBugsが主流になっています。

SpotBugsは、人間がどうしても起こす「うっかり」を補ってくれる存在です。

ストリームの閉じ忘れや、equalsメソッドへの不適切な型の引数などが典型例です。コンパイルは通るのに、動かすと危険な箇所をピンポイントで指摘します。

静的解析とは何をしているのかをざっくり理解する

静的解析は、プログラムを実行せずにソースコードやバイトコードをスキャンして問題を特定する手法です。

プログラムを実際に動かす「動的テスト」だけでは、特定の条件下でしか発生しないバグを見逃してしまうことが多いのです。

静的解析ツールは、何千、何万というコードの断片を、既知の「バグのパターン」と照らし合わせます。

パターン照合の作業は、プロの校正者が文章の文法ミスや論理的な矛盾を指摘するような作業です。

実行環境を用意する必要がないため、開発の早い段階で問題を発見できるのが最大の強みです。

SpotBugsが警告を出すまでの流れ
1
SOURCE / ソースコードソースコードを書くいつもどおりコードを書く
2
BYTECODE / バイトコード.classファイル(バイトコード)SpotBugsが読むのはこちら
3
STATIC ANALYSIS / 静的解析既知のバグパターンと照合プログラムは動かさない
4
WARNING / 警告動かすと危険な箇所を警告例:ストリームの閉じ忘れ/equalsへの不適切な型の引数

SpotBugsが見つけられるバグの種類

SpotBugsは、単なる書き方の好みを指摘するツールではなく、実害のあるバグを見つけます。

具体的には、次のようなバグが挙げられます。

  • Nullポインタの参照
  • 無限ループ
  • 資源(ファイルポインタや接続)の解放漏れ
  • 不適切な同期処理

例えば、String.replace() メソッドの戻り値を利用していないコードはよく見かけます。

Stringは不変(Immutable)なので、戻り値を無視すると置換処理は実質的に何も行われません。

このような「うっかりミス」をコンパイラは検知できませんが、SpotBugsは「このコードは何もしていない」と即座に指摘してくれます。

コンパイル・テストの隙間を補う理由

コンパイルは「文法的に正しいか」をチェックし、テストは「意図通りに動くか」を検証します。

しかし、SpotBugsはその中間にある「実装上の危険」をカバーします。

テストケースをすべてカバーするのには限界があり、稀にしか通らない例外処理ルートなどはテストで見落とされがちだからです。

静的解析は、テストが実行されないコードパスも含めて全方位的にチェックを行います。

つまり、テストコードの書き漏らしを補完する「セーフティネット」のような役割を果たします。

私は、テストを「動的な門番」、静的解析を「静的な監視カメラ」と呼んでいます。両方が揃って初めて、安心して本番リリースに向かえるのです。

なぜFindBugsではなくSpotBugsを使うのか

FindBugsとSpotBugsのどちらを使うかで迷っているなら、答えはSpotBugsです。

findbugs で検索した直後の不安は、読み終える頃には「明日のコミットからSpotBugsを動かす段取り」に変わっているはずです。

解析エンジン・警告パターン・コマンド体系もほぼ引き継いでいるため、FindBugs ≒ SpotBugs という前提で読み進めて構いません。

かつてのスタンダードだったFindBugsは、すでに開発が止まっており、最新のJavaバージョンに対応できていません。理由は明確です。

  • 2015年3月リリースの 3.0.1 を最後にメンテナンスが停滞
  • Java 9以降で導入された新機能やバイトコードの変更に追従できていない
  • 公式サイト findbugs.sourceforge.net も今なお「現在のバージョンは3.0.1(2015年3月リリース)」と表示されたままで、最終リリースから既に11年以上が経過

そのプロジェクトをフォークして、有志のコミュニティが継続的に改善を続けているのがSpotBugsです。

名前は変わっても、中身はFindBugsの解析エンジンそのものです。そこに現代のJavaへの対応を重ねてきた正統な後継と言えます。

FindBugsがメンテナンス終了した背景

FindBugsが止まった理由は、主要な開発者がプロジェクトから離れ、コミュニティ主導の体制への移行がスムーズに進まなかったことにあります。

技術的な負債というよりは、プロジェクト管理の寿命が来たケースです。

Javaは8以降、リリースサイクルが早まり、言語仕様も大きく変わりました。

速くなった言語仕様の変化に追従するには相応の開発リソースが必要ですが、FindBugsの体制では維持が難しくなりました。

広く愛用されていたツールが止まったのは残念でしたが、その設計思想と解析エンジンはSpotBugsにそのまま引き継がれています。

SpotBugsで改善された点と現在の立ち位置

SpotBugsは、Java 21(2023年9月リリースのLTS)に加え、2025年9月リリースの最新LTSであるJava 25にも対応済みです。2026年3月には非LTSのJava 26も出ていますが、現行LTSは引き続きJava 25です。

プラグイン機構もより洗練されています。

開発コミュニティが活発で、GitHubでのIssue対応やプルリクエストの取り込みが頻繁に行われているのが背景にあります。

特に、最新のビルドツール(Gradleの最新版など)との親和性が高いです。

以前のFindBugsで発生していた「ビルドが通らない」「解析が遅い」といったストレスが大幅に軽減されています。

2026年9月時点でも、バイトコードを解析するオープンソースの静的解析ツールとしては、SpotBugsが事実上の標準です。

Java 17・21などのLTSバージョンへの追従も継続しており、当面は安心して長期採用できます。

FindBugsからSpotBugsへの移行3ステップ

「既存プロジェクトで findbugs-maven-plugin がまだ生きている」というケースもよく見ます。

SpotBugsへの乗り換えは想像以上に簡単で、以下の3ステップで完了します。

  1. プラグイン置換: pom.xml / build.gradle の findbugs-maven-plugin や findbugs プラグインを spotbugs-maven-plugin / com.github.spotbugs に書き換える
  2. 抑制アノテーションの依存を置換: com.google.code.findbugs:annotations の依存を com.github.spotbugs:spotbugs-annotations に置き換える。@SuppressFBWarnings はパッケージ(edu.umd.cs.findbugs.annotations)が同じなのでそのまま使え、非推奨の edu.umd.cs.findbugs.annotations.SuppressWarnings を使っている箇所だけ @SuppressFBWarnings に書き換える
  3. 除外フィルタの再利用: 既存の findbugs-exclude.xml はFilterスキーマが互換のため、ファイル名を spotbugs-exclude.xml にリネームしてそのまま流用可能

3ステップの流れを図にすると、次のようになります。

FindBugsからSpotBugsへの移行3ステップ
BEFORE / 移行前findbugs-maven-plugin が現役
1
PLUGIN / プラグイン置換spotbugs-maven-plugin / com.github.spotbugs に書き換えpom.xml / build.gradle のFindBugsプラグインを置き換える
2
ANNOTATION / 抑制アノテーション置換@SuppressWarnings → @SuppressFBWarningsimportは edu.umd.cs.findbugs.annotations.SuppressFBWarnings
3
FILTER / 除外フィルタの再利用findbugs-exclude.xml をリネームして流用Filterスキーマが互換なので、中身は書き換えなくてよい
AFTER / 移行後移行完了

SpotBugsはFindBugsの除外フィルタと同じ書式を読めるので、除外設定が大きくなっていても findbugs-exclude.xml を書き換えずに移行できます。

findbugs spotbugs 移行で迷っているなら、思い切って今日から進めて構いません。

Checkstyle・PMDとの役割分担

よく「CheckstyleがあればSpotBugsはいらないのでは?」と聞かれますが、これらはまったく別物です。

これら3つのツールを組み合わせて使うのがベストです。役割を整理すると以下のようになります。

ツール名解析対象主な目的
Checkstyleソースコードインデント、命名規則などの「見た目」の統一
PMDソースコード未使用変数、複雑すぎるメソッドなどの「コード臭」の検知
SpotBugsバイトコードNullポ、無限ループ、資源漏れなどの「論理的なバグ」の検知

Checkstyleが「マナー」を教える先生だとしたら、SpotBugsは「爆弾(バグ)」を見つけてくれる爆発物処理班のような存在です。

見た目が綺麗でも、中身に爆弾が埋まっていたら意味がありませんよね。

「3つ全部は重い、まず1つだけ入れたい」という現場のために、私の判断軸を共有します。

  • 本番障害を1件でも減らしたい → SpotBugs(Correctness警告がそのまま事故予防になる)
  • 新人が多くコードレビューが追いつかない → Checkstyle(命名・インデントの揃え直しでレビュー時間を半減できる)
  • 古いコードベースのリファクタリングを進めたい → PMD(重複・複雑度を可視化して着手場所を決められる)

新規プロジェクトなら「Checkstyle → SpotBugs → PMD」の順で入れるのが無理のない進め方です。

Checkstyleは警告をすぐ全消しできて達成感があり、ツールへの心理的抵抗が下がるためです。

SpotBugsを最初に入れて1,000件超の警告を見せてしまうと、チームが「もう触りたくない」と拒絶反応を起こすことがあるので注意してください。

あわせて読む

SpotBugsを導入する前に知っておきたい前提知識

SpotBugsを導入する前に、まず自分のプロジェクトの環境を確認しましょう。

対応しているJavaのバージョンや、使用しているビルドツールによって、設定方法が若干異なるためです。

また、静的解析ツールを導入する際のマインドセットも重要です。最初から完璧を求めすぎると、膨大な警告に圧倒されて挫折してしまいます。

ツールはあくまで「人間のサポート役」であり、主役は開発者自身であることを忘れてはいけません。

Javaバージョンと対応状況

SpotBugsを動かすにはJDK 11以上が必要です。一方で、解析対象のコードはJava 8など古いバージョンでコンパイルしたものでも構いません(公式README)。

つまり、Java 8のプロジェクトでも、ビルドを実行するJDKを11以上にすれば最新版を使えます。本体の最新は2026年8月19日リリースの4.10.4です(更新履歴は GitHub Releases で確認できます)。

ビルドツールは、Maven・Gradle・Antに対応しています。

MavenとGradle向けのプラグインが公式に提供されており、設定ファイルに数行書き足すだけで既存のビルドに組み込めます。

SpotBugsで見つからないバグもある

SpotBugsを導入すればバグがゼロになる、という期待は禁物です。

なぜなら、静的解析には「誤検知(False Positive)」と「検知漏れ(False Negative)」が必ず存在するからです。

例えば、業務ロジック的な間違い(「10%引きにするはずが20%引きになっている」など)はSpotBugsには分かりません。

また、文脈上は安全であっても、コードの構造だけを見て「Nullポインタの可能性があります」と警告を出すこともあります。

ツールが出す指摘を鵜呑みにせず、最終的には人間が「これは修正すべきか、無視すべきか」を判断する姿勢が大切です。

SpotBugsをJavaプロジェクトに導入する方法

導入は驚くほど簡単です。主要なビルドツール向けのプラグインが完備されており、依存関係を追加するだけで動作するよう設計されています。

ここでは、現在のJava開発で主流となっているMavenとGradle、そして日々の開発効率を上げるためのIDE(IntelliJ IDEA)での設定方法を紹介します。

導入方法の比較(Maven・Gradle・IDE)

まずは4つの主要な導入経路を一望しておきましょう。プロジェクトの性格と運用フェーズで選ぶのが正解です。

導入経路設定の手間向いているケース弱点
Mavenプラグイン低(pom.xmlに数行)レガシー保守 / CI標準化柔軟性はGradleに劣る
Gradleプラグイン低新規・モダンなJava開発プラグイン側の破壊的変更が比較的早い
IntelliJプラグイン最低個人開発 / コミット前チェックCIには不向き
Eclipseプラグイン低Eclipse既存ユーザー / 旧FindBugs移行解析速度がやや遅い

迷ったら、まずはMavenかGradleのプラグインでCIに組み込むのが王道です。個人開発であればIntelliJプラグインだけでも十分機能します。

導入から最初の警告確認、CIへの組み込みまでの流れは次のとおりです。

導入から最初の警告確認、CIへの組み込みまで
1
ビルドツールを確認
Maven か Gradle か?
MAVENpom.xml に spotbugs-maven-plugin 4.10.4.1 を追加mvn compile site でHTMLレポートを確認
GRADLEbuild.gradle に com.github.spotbugs 6.5.11 を追加./gradlew spotbugsMain でHTMLレポートを確認
2
Correctness × High から修正誤検知は除外フィルタで抑制
3
CI / 自動化GitHub Actions に組み込み警告の増加をブロック
あわせて読む

MavenプロジェクトにSpotBugsを組み込む手順

Mavenの場合は、pom.xml の build セクション内に spotbugs-maven-plugin を追加します。

<plugin>
    <groupId>com.github.spotbugs</groupId>
    <artifactId>spotbugs-maven-plugin</artifactId>
    <version>4.10.4.1</version>
    <executions>
        <execution>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
</plugin>

これだけで、mvn spotbugs:check を実行すれば解析が始まります。

バグが見つかった場合にビルドを失敗させたいなら、このように check ゴールを設定しておくのが定石です。

リリースビルドでは必ず check が走るように設定しておくと、警告を見落としたまま出荷するのを防げます。プラグインの 4.10.4.1 は、SpotBugs本体4.10.4を使います。

プラグインの最新版は Maven Central で確認してください。Mavenを動かすJDKは11以上が必要です。

HTMLレポート生成と確認

mvn spotbugs:check はビルドを成功させるか失敗させるかを判定するためのゴールです。

警告の中身を一覧でじっくり確認する用途には向いていません。

ブラウザで警告一覧を見たい場合は、reporting セクションに同じプラグインを追加します。

<reporting>
    <plugins>
        <plugin>
            <groupId>com.github.spotbugs</groupId>
            <artifactId>spotbugs-maven-plugin</artifactId>
            <version>4.10.4.1</version>
        </plugin>
    </plugins>
</reporting>

設定できたら、mvn compile site を実行してください。

target/site/spotbugs.html にレポートが生成され、ブラウザで開けば警告の一覧・詳細をGUIツールなしで確認できます。

「まず警告の全体量を把握したい」という段階では、HTMLレポートが一番手軽です。

警告を1件ずつソースと見比べたいときは、mvn spotbugs:gui で専用GUIを開く方法もあります(先に mvn compile と mvn spotbugs:spotbugs で解析結果を作っておきます)。

Gradleプロジェクトでの設定方法

Gradleの場合は、build.gradle にプラグインを適用するだけです。

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

plugins {
    id "java"
    id "com.github.spotbugs" version "6.5.11"
}

spotbugs {
    ignoreFailures = false
    showStackTraces = true
    effort = Effort.valueOf('DEFAULT')
    reportLevel = Confidence.valueOf('MEDIUM')
}

// ブラウザで見られるHTMLレポートを出力する
spotbugsMain {
    reports {
        html {
            required = true
        }
    }
}

6.x系のプラグインでは、effort や reportLevel に文字列ではなく列挙型(Effort / Confidence)を渡します。古い記事の effort = 'default' をそのまま貼るとエラーになるので注意してください。

解析は ./gradlew spotbugsMain(テストコードも含めるなら ./gradlew check)で実行します。HTMLレポートは build/reports/spotbugs/ 配下に出力されます。

開発中は ignoreFailures = true にしておき、CI環境では false にして厳格にチェックする、という使い分けがやりやすい設定です。

Gradleプラグインの最新版は Gradle Plugin Portal で確認してください。本記事の 6.5.11 はSpotBugs 4.10.4を使い、設定例の書き方にはGradle 8.2以上が必要です(詳細は公式リリースノート)。

IntelliJ IDEAでSpotBugsを実行する方法

ビルドツールでの実行も重要ですが、一番効率がいいのは「コードを書いているその瞬間」に指摘をもらうことです。

IntelliJ IDEAを使っているなら、「SpotBugs」プラグインをインストールしましょう。

プラグインを導入すると、エディタ上で右クリックして「SpotBugs」→「Analyze Selected Files」(プロジェクト全体なら「Analyze Project Files…」)と選ぶだけで、現在のファイルやプロジェクト全体をスキャンできます。

見つかった警告はエディタの下部に一覧表示され、該当箇所をダブルクリックすればすぐに修正に着手できます。

コミット前にIDE上で一度スキャンする習慣をつけておくと、CIで落ちてから直す手戻りが減ります。

EclipseでのSpotBugs導入

Eclipseユーザーは「findbugs eclipse」で検索する人も多いですが、現在Eclipse Marketplaceで配布されているのはSpotBugsの公式プラグインです。

旧FindBugsプラグインがインストールされたままでも、まずはアンインストールしてからSpotBugsに置き換えてください(両方入っていると警告が二重に出て混乱のもとです)。

  • Eclipseメニュー Help → Eclipse Marketplace を開く
  • 検索欄に「SpotBugs」と入力し、「SpotBugs Eclipse plugin」をInstall
  • 再起動後、対象プロジェクトを右クリック → SpotBugs → Find Bugs で実行
  • 結果は「Bug Explorer」ビュー(Window → Show View → Other... → SpotBugs)で確認

「Bug Explorerに何も表示されない」という症状は、対象プロジェクトのビルド出力(classファイル)が生成されていないケースがほとんどです。

先に Project → Build Project で一度ビルドしてから、再実行してください。

プラグイン設定の Window → Preferences → Java → SpotBugs から、解析する優先度(Low / Medium / High)や対象カテゴリも調整可能です。

SpotBugsの解析結果をどう読み解けばいいのか

解析を実行すると、驚くほど多くの警告が出ることがあります。SpotBugsが細かいパターンまでチェックしているためです。

すべての警告に目を通すのは大変ですが、SpotBugsには「カテゴリ」と「優先度」という仕組みがあります。

これらを理解すれば、修正すべき優先順位が明確になり、効率的に品質を高められます。

Bugカテゴリと優先度(Priority)の考え方

SpotBugsの警告には、大きく分けて以下のようなカテゴリがあります。

  • Correctness(正当性): 明らかなバグ。すぐに直すべき。
  • Security(セキュリティ): 脆弱性につながる問題。
  • Performance(パフォーマンス): 効率の悪い書き方。
  • Bad Practice(悪い慣習): Javaのセオリーに反する書き方。

これに加えて、優先度(High, Medium, Low)が割り振られます。まずは「Correctness」の「High」から手をつけるべきです。

Lowレベルの警告は、正直なところ「好みの問題」に近いものも多いため、初心者のうちは無視しても構いません。

「全部直すべき?」と迷ったときの判断基準

警告を全部消そうとして、不自然なコードになってしまっては本末転倒です。ツールの指摘が、常に正しいとは限らないのですから。

判断に迷ったときは「そのコードで実際に障害が起きる可能性があるか」を自問自答してください。

例えば、プライベートメソッド内で、呼び出し元が限定されており絶対にNullにならない変数に対して「Nullの可能性があります」と出た場合。

このときは、コードを無理に変えるのではなく、SpotBugsの設定でその箇所を除外(Exclude)するか、アノテーションで抑制するのが健全な判断です。

この判断の流れを図にすると、次のようになります。

警告を直すか・除外するか・抑制するかの判断(Q1から順に答える)
QUESTION / 質問
はい
いいえ
Q1. そのコードで実際に障害が起きる可能性があるか?SpotBugsの警告が出たら、まずこれを自問する
コードを修正する
Q2へ
Q2. チームで合意できるか?「はい」は設計判断として明確な場合
Excludeフィルタで除外
@SuppressFBWarnings で抑制個別ケースとして、理由を明記する

初心者が最初に注目すべき警告の種類

まずは「NullPointer」と「Resource Leak」の2点に絞って見てみましょう。

Javaで最も発生しやすく、かつ影響が大きいバグだからです。

「変数 x がこのパスでNullになる可能性があります」という指摘が出たら、その前の処理を慎重に確認してください。

また、InputStream や Connection がクローズされていないという指摘は、将来的なシステムダウンを未然に防いでくれる貴重なアドバイスです。

NullPointerとリソースリークの2種類を直すだけでも、アプリケーションの安定性ははっきり上がります。

よく出る警告例と、実務での現実的な対処法

ツールが何を怒っているのかを理解すれば、指摘されるのが怖くなくなりますよ。

SpotBugs(FindBugs)の主要バグパターン早見表

個別の警告を解説する前に、SpotBugsでよく出るパターンを早見表でざっと眺めておきましょう。

「findbugs エラー 一覧」を調べに来た方は、まずこの表を眺めてから個別の対処法に進むと理解が早いです。

パターンIDカテゴリ意味典型的な対処
NP_NULL_ON_SOME_PATHCorrectness分岐次第でnullになる変数を未チェックで参照事前チェック追加 / Optional化
NP_ALWAYS_NULLCorrectness常にnullの変数を参照している初期化忘れ / ロジック見直し
OS_OPEN_STREAMBad Practiceストリームをcloseしていないtry-with-resourcesに置き換え
RR_NOT_CHECKEDBad Practiceread()の戻り値(読み込み件数)を未確認戻り値の確認・例外処理追加
EI_EXPOSE_REPMalicious Code Vuln内部の可変オブジェクトを直接公開している防御的コピーを返す / イミュータブル化
DM_DEFAULT_ENCODINGInternationalizationプラットフォーム依存の文字エンコーディングを使用明示的にUTF-8等を指定
SE_NO_SERIALVERSIONIDBad PracticeSerializableクラスにserialVersionUID未定義serialVersionUIDを定義
EQ_DOESNT_OVERRIDE_EQUALSStyle親クラスのequalsをオーバーライドしていないequals/hashCodeをセットで実装

このうち Correctnessカテゴリ(NP_*) は実害に直結するため最優先で潰します。

Bad Practiceは将来的なバグの種なので、新規コードでは出さない方針が安全です。

NullPointerExceptionにつながりやすい警告

よく出るのが NP_NULL_ON_SOME_PATH という警告です。

これは「ある条件分岐ではNullになる可能性がある変数を、チェックせずに参照している」という指摘です。

public void printLength(String str) {
    if (str == null) {
        System.out.println("Nullです");
    }
    // ここで警告!strがnullの場合でもlength()を呼ぼうとしている
    System.out.println(str.length());
}

このような場合、単にチェックを増やすだけでなく、Java 8以降なら Optional を使って設計を見直すのも一つの手です。

SpotBugsは、私たちの設計の甘さを突いてくる優秀なコンサルタントだと思って付き合いましょう。

パフォーマンスやメモリリーク関連の指摘

RR_NOT_CHECKED や OS_OPEN_STREAM など、資源の扱いに関する警告も頻出します。

特に、例外が発生したときにストリームが閉じられないコードは、テスト環境では動いても本番環境で長時間稼働させると「Too many open files」エラーが発生します。

Java 7以降であれば、try-with-resources 文を使うことで、これらの警告のほとんどは解消できます。

もし古いコードで finally 句の中で手動で閉じているなら、この機会に現代的な書き方にリファクタリングしてしまいましょう。

設計のクセが原因で出やすい警告

EI_EXPOSE_REP という警告に悩まされる人も多いでしょう。これは「内部の可変オブジェクトをそのまま返している」という指摘です。

public Date getBirthDate() {
    return birthDate; // Dateは可変なので、外部から書き換えられてしまう
}

この警告をあえて無視する場合は、@SuppressFBWarnings アノテーションを使って理由とともに抑制するのが正しいやり方です。

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

@SuppressFBWarnings(
    value = "EI_EXPOSE_REP",
    justification = "このDateオブジェクトは呼び出し元から変更されないことがチームで合意されている"
)
public Date getBirthDate() {
    return birthDate;
}

これを厳格に守ると、すべてのゲッターでコピーを返す必要があり、コードがごちゃごちゃになります。

チームで話し合って「この警告はあえて無視する」というルールを決めておくのも、一つのやり方です。

すべての警告に従うのが正解ではなく、チームにとって最適なバランスを見つけるのがプロの仕事です。

ただし、@SuppressFBWarnings の 乱用には要注意 です。

警告を消したいからと justification に "intentional" とだけ書いて抑制を重ねると、あとから見た人には「安全だから抑制した箇所」と「とりあえず黙らせた箇所」の区別がつきません。

その結果、本物のバグまで @SuppressFBWarnings で覆い隠されてしまうことがあります。

justificationには必ず「なぜ安全と判断したか」の根拠 を書いてください。

「チームで合意済み」だけでは、3ヶ月後の自分や新メンバーが判断できません。

SpotBugsをチーム開発で活かすための使い方

個人開発ならIDEで見ているだけで十分ですが、チーム開発では「仕組み」に組み込むことが必須です。

個人の意識に頼った品質管理は、忙しくなると必ず形骸化してしまいます。

チーム全員が同じ基準でコードをチェックし、一定の品質を下回るコードをリポジトリに入れないようにする。そのための「自動化された門番」を構築しましょう。

CIに組み込むときの考え方と注意点

GitHub ActionsやJenkinsなどのCIツールで、プルリクエストが作成されるたびにSpotBugsを実行するように設定します。

「新規に追加された警告が1つでもあればビルドを失敗させる」という運用が理想です。

ただし、これを最初から既存のプロジェクトでやると、数千件の警告のせいで何もできなくなります。

まずは現状の警告数を「ベースライン」として記録し、そこから増やさないという運用から始めるのが現実的です。

CIの結果をチャットに通知するようにしておくと、警告が増えたことにその場で気づけるので、ベースラインを守りやすくなります。

GitHub Actionsワークフロー(YAML)の設定例

設定は .github/workflows/spotbugs.yml のようなファイルをリポジトリに置くだけです。

Gradleプロジェクトの最小構成は次のようになります。

name: SpotBugs

on:
  pull_request:
    branches: [main]

jobs:
  spotbugs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-java@v5
        with:
          distribution: 'temurin'
          java-version: '21'
      - run: ./gradlew spotbugsMain

Mavenプロジェクトの場合は、最後のステップを ./gradlew spotbugsMain から mvn spotbugs:check に置き換えるだけで、同じ仕組みがそのまま使えます。

プルリクエスト作成時にだけ動かす on: pull_request にすれば、無駄なCI時間も使いません。

既存コードが大量に警告を出す場合の進め方

古いプロジェクトにSpotBugsを導入すると、絶望的な数の警告が出ることがあります。

その場合の対処法は、一気に直そうとせず「除外設定(exclude filter)」をフル活用することです。

まずは全警告を無視する設定からスタートし、重要なカテゴリだけを少しずつ有効にしていきます。

あるいは、新規に作成・修正したファイルだけを解析対象にするようなスクリプトを組むのも良いでしょう。

リファクタリングは「楽しみながら少しずつ」が継続のコツです。

除外設定のXMLファイル(例:spotbugs-exclude.xml)は以下のように記述します。

<FindBugsFilter>
    <!-- レガシーコードのパッケージをまとめて除外 -->
    <Match>
        <Package name="com.example.legacy"/>
    </Match>
    <!-- 特定クラスの特定バグパターンのみ除外 -->
    <Match>
        <Bug pattern="EI_EXPOSE_REP"/>
        <Class name="com.example.model.UserDto"/>
    </Match>
</FindBugsFilter>

MavenではこのXMLファイルを <excludeFilterFile>spotbugs-exclude.xml</excludeFilterFile> としてプラグイン設定に指定し、Gradleでは spotbugs { excludeFilter = file("spotbugs-exclude.xml") } と記述することで有効になります。

大きなプロジェクトに後から入れる場合の進め方の例です。

長く育ったレガシーなJavaプロジェクトにSpotBugsを後から導入すると、初回スキャンで 千件単位 の警告が出ることも珍しくありません。

その場合は、次の優先順位で段階的に減らしていくのが現実的です。

  • 最初: Correctness × High を最優先で修正する。Nullチェック漏れなど、本番の例外に直結する警告から先につぶす
  • 次: OS_OPEN_STREAM などリソースの閉じ忘れを try-with-resources に置き換える。件数が多くても機械的に直せる
  • 最後: EI_EXPOSE_REP 系は @SuppressFBWarnings で意図を明記して抑制、もしくはイミュータブル化。残った警告は「設計判断として残す」ものだけ

ポイントは「全部直す」を諦めること。

優先度を絞らずに根性で全件対応しようとすると、途中で「どうせ直しきれない」と全員が見るのをやめてしまいがちです。

「ベースラインからの増分ゼロ」を最初の半年のゴールにする のが、現場で続けるコツです。

逆に、参考までに失敗例も共有します。

別の現場で「リリース前に全警告を消す」という号令がかかり、有効性検証なしに @SuppressFBWarnings を200箇所近くばら撒きました。

半年後の障害調査で「なぜここで抑制した?」が誰にもわからなくなり、すべて剥がし直す羽目になりました。

抑制は減らすより増やす方が10倍簡単 で、剥がす作業は元の警告対応より重いことだけは断言できます。

レビュー負荷を下げるための運用ルール例

コードレビューで「ここNullチェック漏れてますよ」と指摘するのは、お互いに精神を削ります。

SpotBugsを導入していれば、そういった単純なミスはツールが指摘してくれるため、人間は「設計思想」や「アルゴリズムの妥当性」といったクリエイティブな議論に集中できます。

「SpotBugsが通っていないコードはレビューに出さない」というルールをチームで決めておくと、レビューで単純なミスを指摘し合う時間を減らせます。

機械にできることは機械に任せ、人間は人間にしかできない仕事をしましょう。

あわせて読む

SonarQube(SonarCloud)と組み合わせて使う場合

すでに社内でSonarQube/SonarCloudを使っている現場では、「SpotBugsの結果もSonarQubeに集約したい」というニーズがよく出ます。

SonarQubeは公式プラグインの sonar-findbugs(現在もFindBugs時代の名前のまま配布)を使うことで、SpotBugsの解析結果を取り込めます。

  • SonarQube管理画面の Marketplace から Findbugs プラグインをインストール
  • Maven/Gradleで先にSpotBugsを実行し、spotbugsXml.xml(XML形式レポート)を出力
  • sonar-scanner 実行時に sonar.java.spotbugs.reportPaths でレポートパスを指定

注意点として、SonarQube自体にも独自のJavaルール(Sonar Java)が組み込まれており、ルールが重複することがあります。

ベースラインを揃えるため、最初は SpotBugsをCorrectness系のみ・Sonar Javaをコード品質系のみ といった役割分担で運用するとノイズが減ります。

あわせて読む

SpotBugsが向いているケース・向いていないケース

これほど便利なSpotBugsですが、すべてのプロジェクトで万能ではありません。

特性を理解して、適材適所で活用することが重要です。

導入効果が高いプロジェクトの特徴

大規模なエンタープライズ系システムや、長期にわたってメンテナンスが必要なプロジェクトでは、SpotBugsは絶大な効果を発揮します。

開発者が入れ替わっても、ツールが一定の品質を強制してくれるからです。

また、ミッションクリティカルな、バグが許されない金融系やインフラ系のプロジェクトでも必須です。

SpotBugsだけに頼ると起きがちな誤解

「SpotBugsがグリーンだからこのコードは完璧だ」と思い込むのが一番危険です。

先述の通り、SpotBugsは「ロジックの正しさ」までは見ていないのですから。

不適切なビジネスロジック、遅すぎるSQL、不親切なUIなど、ユーザー体験を損なう問題は静的解析では見つかりません。

ツールはあくまで「最低限のガードレール」です。ユニットテスト・手動テスト・コードレビューと重ねて、防御を多層にしてください。

冒頭で触れたとおり、私自身はSpotBugsがどうもしっくりこず、JetBrainsのQodanaに乗り換えました。決め手は、UIや結果の見せ方を含めたモダンな使い心地です。

それでも、SpotBugsは枯れていて情報量が多く、Maven/Gradleへの組み込み実績も十分です。無料のオープンソースだけで完結させたい現場や、FindBugs時代の設定資産がある現場なら、今でも最初に入れる価値があります。

「ツールの見た目や使い心地も重視したい」なら、Qodanaも候補に入れて比べてみてください。

あわせて読む

SpotBugs導入でよくある質問(FAQ)

記事内で扱いきれなかった、現場でよく聞かれる質問をまとめます。

Q1. SpotBugsとFindBugsは互換性がありますか?

A1. はい、設定ファイル・抑制アノテーション・バグパターンIDのほとんどがそのまま使えます。@SuppressFBWarnings アノテーションも引き継がれています。既存の findbugs-exclude.xml も、spotbugs-exclude.xml としてリネームすれば動作します。プラグイン名(findbugs-maven-plugin → spotbugs-maven-plugin)の置換だけで移行できるケースが大半です。

Q2. SpotBugsはJava 21・25でも動きますか?

A2. はい、動きます。SpotBugs本体の実行にはJDK 11以上が必要ですが、解析対象はJava 8など古いバージョンでコンパイルしたコードでも構いません。Java 17・21 LTSに加え、2025年9月リリースのJava 25 LTSにも対応済みです。

Q3. SpotBugs単体で動かすGUIはありますか?

A3. あります。SpotBugsをダウンロードして展開後、bin/spotbugs(macOS/Linux)または bin\spotbugs.bat(Windows)を実行してください。Swingベースの専用GUIが起動します。Mavenプロジェクトなら mvn spotbugs:gui でも開けます。

Maven/Gradleを使わないその場限りの解析や、レポートの目視確認に便利です。ただし見た目がレトロで、複数プロジェクトを横断する分析にはやや手狭です。

日々の運用では、CIでXMLレポートを出力し、IntelliJプラグインで対象ファイルを開く形が扱いやすいです。GUI単体は「初期検証用」と割り切るとよいでしょう。

Q4. SpotBugs・PMD・Checkstyleはどれを使うべきですか?

A4. 3つは役割が異なるため、原則は併用です。本記事の「Checkstyle・PMDとの役割分担」で詳しく整理していますが、まず1つだけ入れるならSpotBugs(Correctness警告がそのまま事故予防になる)を推奨します。コードレビュー負荷が高い現場ではCheckstyleを並行導入してください。

Q5. IntelliJでSpotBugsがバグを検出しないのはなぜですか?

A5. 多くの場合、ビルド出力(target/classes や build/classes)が生成されていません。SpotBugsはバイトコード(.classファイル)を解析するため、ソースだけ存在しても検査できないのです。Build → Build Project でフルビルドしてから、SpotBugsを再実行してください。

mvn clean 直後に解析を回すと、クラスファイルが消えているせいで「何も見つからない」結果になり、直ったと勘違いしやすいので注意してください。

Q6. SpotBugsは無料で使えますか?

A6. はい、無料です。SpotBugsはGNU Lesser General Public License(LGPL)で公開されているオープンソースソフトウェアで、Maven・Gradle・Eclipse・IntelliJ IDEA向けのプラグインもすべて無償で利用できます。商用プロジェクトへの組み込みも制限なく可能です。

Q7. SpotBugsの誤検知にはどう対処すればいいですか?

A7. 誤検知(False Positive)が多い場合は、無理にコードを変更せず、除外設定(spotbugs-exclude.xml)または @SuppressFBWarnings アノテーションで対応するのが適切です。本記事の「既存コードが大量に警告を出す場合の進め方」で具体的な設定方法を解説しています。

Q8. SpotBugsとFindBugsはどちらを使うべきですか?

A8. 新規プロジェクトでも既存プロジェクトでも、迷わずSpotBugsを選んでください。FindBugsは2015年の3.0.1を最後に開発が止まっており、Java 9以降のプロジェクトでは動作しません。SpotBugsはFindBugsの解析エンジンを引き継いだ正統な後継であり、設定ファイルやアノテーションもほぼそのまま流用できます。

まとめ:SpotBugsの効果的な活用法

SpotBugsを「口うるさい小姑」ではなく「頼れる副操縦士」として取り入れることが、Java開発成功の近道です。

どれほど技術を磨いても、私たちは人間である以上、疲れや油断から必ずミスを犯すからです。

SpotBugsを導入することで、以下のような未来が手に入ります。

  • 深夜の緊急呼び出し(NullPointerExceptionなど)が激減する
  • コードレビューがマサカリの投げ合いではなく、建設的な議論になる
  • 「自分のコードはツールのお墨付きをもらっている」という自信を持ってリリースできる

最初は設定に手間取るかもしれませんし、警告の多さに嫌気がさすかもしれません。

それでも、警告の1件1件は「なぜこの書き方が危ないのか」を教えてくれます。Javaの細かい仕様を学ぶ教材としても役立ちます。

REVISIONS / 改訂履歴
REV.DATE内容
62026-10-15図解を描き直し(図面のデザインにそろえた)
52026-10-14体験談の書き方を見直し、導入の進め方を一般的な手順として整理
42026-08-092026年8月時点の情報で全体を見直し(古い記述を2件更新)
32026-05-052026年5月時点の情報で全体を見直し
… ほか1回の改訂
12026-02-07初版
NEXT READ本棚から1本

AIで開発を組み直すなら、まずこの5冊から

入門・実践・設計まで、Claude Codeの本をレベル別に5冊選んで比べました。

→ おすすめ5冊を見る

  • この記事を書いた人
  • 最新記事

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

Java入門