Eclipse上のJavaコードでブレークポイントを置けなくなるケースとは?Spring Boot開発の新人エンジニア向けに解説

こんにちは。ゆうせいです。

今回は、Eclipse上のJavaコードで「本来ならブレークポイントを置けるはずなのに、置けなくなっている」ケースについて解説します。

Spring Bootで開発していると、ControllerやServiceやDAOの行にブレークポイントを置いて、処理を止めながら確認することがありますよね。

ところが、ある日突然、左側の余白をダブルクリックしてもブレークポイントが付かない。

ブレークポイントを置いたつもりなのに、処理が止まらない。

丸い印は付いているのに、実行時に無視される。

このようなことがあります。

原因はいくつかありますが、大きく分けると次の4種類です。

分類よくある原因新人向けのイメージ
Eclipse操作の問題ブレークポイント全体が無効、別ビューで開いている信号機の電源が切れている
起動方法の問題DebugではなくRunで起動している録画モードではなく普通に再生している
ソースと実行classの不一致編集しているJavaと実際に動いているclassが違う地図と実際の道路が違う
コードの性質の問題実行されない行、コメント行、空行、ラムダや自動生成コード止まる場所がそもそも道路ではない

Eclipseのデバッグ機能では、ブレークポイントはEclipseのブレークポイント管理機能によって管理されます。Eclipse公式ヘルプでも、ブレークポイントはBreakpoint Managerによって追加・削除され、全体として有効・無効を切り替えられると説明されています。

つまり、ブレークポイントは単なる画面上の丸印ではありません。

Eclipse、Javaのコンパイル結果、起動中のJVM、実行されるソースコードが正しくつながって初めて機能します。

まず確認すべき結論

最初に、よくある原因を結論としてまとめます。

症状よくある原因確認する場所
左の余白を押しても丸が付かないJavaエディタではない、行に実行コードがない、Eclipseの表示や設定問題開いているファイル、行の種類、Problemsビュー
丸は付くが止まらないRunで起動している、該当処理が呼ばれていないDebug起動、リクエストURL、ログ
丸に斜線が付いているブレークポイントが無効化されているBreakpointsビュー
全てのブレークポイントで止まらないSkip All Breakpointsが有効Debugビュー、Breakpointsビュー
置けるが「行番号情報がない」と出るclassにデバッグ情報が入っていないコンパイラ設定、Maven/Gradle設定
昔の行で止まる、変な位置で止まるソースとclassがずれているClean、再ビルド、起動対象プロジェクト

新人エンジニアは、いきなり難しい設定を見る前に、まず「Debug起動しているか」「その行は本当に実行されているか」「ブレークポイント全体が無効になっていないか」を確認してください。

ケース1:DebugではなくRunで起動している

一番よくあるのが、Spring BootアプリをDebugではなくRunで起動しているケースです。

Eclipseには、通常実行とデバッグ実行があります。

起動方法意味ブレークポイントで止まるか
Run As普通に実行する止まらない
Debug Asデバッグ用に実行する止まる

Spring Bootなら、次のように起動します。

プロジェクトを右クリック
Debug As
Spring Boot App

または、mainメソッドがあるクラスを右クリックして、次のように起動します。

Debug As
Java Application

Run Asで起動している場合、Eclipse上にブレークポイントの丸印が付いていても、処理は止まりません。

たとえるなら、監視カメラを設置したけれど録画モードにしていないようなものです。

カメラはそこにあります。

でも、記録も停止もできません。

ケース2:Skip All Breakpointsが有効になっている

Eclipseには、すべてのブレークポイントを一時的に無視する機能があります。

英語ではSkip All Breakpointsです。

この機能がオンになっていると、ブレークポイントを置いていても止まりません。

BreakpointsビューやDebugビュー周辺に、ブレークポイントをすべてスキップするボタンがあります。

新人エンジニアが知らないうちにクリックしてしまい、「ブレークポイントが効かない!」となることがあります。

状態動作
Skip All Breakpointsがオフブレークポイントで止まる
Skip All Breakpointsがオン全ブレークポイントを無視する

Breakpointsビューを開いて、全体無効になっていないか確認してください。

Eclipse公式ヘルプでも、ブレークポイントの有効・無効はBreakpoint Managerによって制御できると説明されています。

たとえるなら、赤信号を全部無効にするスイッチが入っている状態です。

交差点ごとの信号は存在します。

でも、全体スイッチで「信号を使わない」設定になっているので止まりません。

ケース3:個別のブレークポイントが無効になっている

全体ではなく、個別のブレークポイントだけが無効になっている場合もあります。

この場合、ブレークポイントの丸に斜線が入っていたり、Breakpointsビューでチェックが外れていたりします。

見た目意味
通常の丸有効なブレークポイント
斜線付き、薄い表示無効なブレークポイント
Breakpointsビューでチェックなしそのブレークポイントだけ無効

確認手順です。

Window
Show View
Breakpoints

または、DebugパースペクティブでBreakpointsビューを表示します。

対象のブレークポイントにチェックが入っているか確認しましょう。

ケース4:実行されない行に置こうとしている

Javaでは、ブレークポイントを置ける行と置けない行があります。

基本的に、実行可能なコード行に置きます。

行の種類ブレークポイントを置けるか理由
変数代入置ける実行される処理だから
メソッド呼び出し置ける実行される処理だから
return文置ける実行される処理だから
コメント行置けない実行されないから
空行置けない実行されないから
import文通常は置かない実行時の処理行ではないから
クラス宣言だけの行止まらないことが多い処理本体ではないから

悪い例です。

// 車一覧を表示する処理

コメント行は実行されません。

ブレークポイントを置いても意味がありません。

良い例です。

List<CarDto> carList = carsDao.findAll();

このような実行される行に置きます。

たとえるなら、電車を止めたいなら線路上に停止位置を作る必要があります。

駅の案内板やポスターに停止位置を作っても、電車は止まりません。

ケース5:その処理がそもそも呼ばれていない

ブレークポイントは置けている。

Debug起動もしている。

それでも止まらない。

この場合、そもそもそのメソッドが呼ばれていない可能性があります。

Spring Bootでは、URL、HTTPメソッド、Controllerのマッピングが少し違うだけで、想定したメソッドに入りません。

例を見てください。

@GetMapping("/cars/search")
public String search() {
    System.out.println("検索処理です");
    return "cars/search";
}




このメソッドにブレークポイントを置いているとします。

しかし、ブラウザで次のURLにアクセスしていたらどうでしょうか。

/car/search

carsではなくcarです。

この場合、別のURLなので、このメソッドは呼ばれません。

また、GETとPOSTの違いでも呼ばれません。

@PostMapping("/cars/search")
public String searchPost() {
    return "cars/search";
}




このメソッドはPOST用です。

ブラウザでURLを直接入力してGETアクセスしても、このメソッドには入りません。

確認項目見ること
URL@GetMappingや@PostMappingと一致しているか
HTTPメソッドGETなのかPOSTなのか
Controllerクラス同じURLの別Controllerがないか
ログメソッド先頭のログが出ているか

切り分けのために、メソッド先頭に一時的にログを入れてみましょう。

System.out.println("searchメソッドに入りました");

このログが出ないなら、ブレークポイント以前に、そのメソッドが呼ばれていません。

ケース6:ソースコードと実行中のclassファイルがずれている

Eclipseで表示しているJavaファイルと、実際にJVMで動いているclassファイルがずれていると、ブレークポイントが効かなかったり、変な行で止まったりします。

Javaは、.javaファイルをそのまま実行しているわけではありません。

.javaをコンパイルして、.classファイルにしてから実行します。

Oracleのjavacドキュメントでも、javacはJavaソースファイルを読み取り、Java Virtual Machineで実行されるクラスファイルへコンパイルすると説明されています。

ファイル役割
.java人間が書くソースコード
.classJVMが実行するコンパイル後のファイル

つまり、Eclipseで見ている.javaと、実際に動いている.classが一致していないと、ブレークポイントが正しく動きません。

よくある原因です。

原因内容
自動ビルドがオフ保存してもclassが更新されていない
ビルドエラーが残っている新しいclassが生成されていない
別プロジェクトを起動している編集しているプロジェクトと実行中プロジェクトが違う
古いjarを実行しているEclipse上のコードではなく古い成果物が動いている
Maven/Gradleの出力先がずれている想定と違うclassが実行されている

この場合は、次の操作を試します。

Project
Clean

そして、対象プロジェクトを選んで再ビルドします。

Mavenプロジェクトなら、次の操作も有効です。

プロジェクトを右クリック
Maven
Update Project

Spring Bootアプリを一度停止し、再度Debug起動することも大切です。

古いアプリが裏で動き続けていると、いくらEclipseで修正しても反映されません。

ケース7:コンパイル時に行番号のデバッグ情報が入っていない

Javaのブレークポイントは、ソースコードの行番号とclassファイル内のデバッグ情報を使って対応します。

コンパイル時に行番号情報が含まれていないと、Eclipseが「このソースのこの行で止める」と判断しにくくなります。

javacにはデバッグ情報を制御する-gオプションがあります。IBMのJavaビルドツール向けドキュメントでは、Ant、Maven、Gradleでsource、lines、varsといったデバッグ情報を含める設定例が紹介されています。

ブレークポイント関連で重要なのは、特にlines、つまり行番号情報です。

デバッグ情報意味不足すると困ること
source元のソースファイル名どのソースか対応しにくい
lines行番号情報ブレークポイント位置が対応しにくい
varsローカル変数情報変数名が見えにくい

通常、EclipseやMavenで普通に開発している場合はデバッグ情報が含まれることが多いです。

しかし、特殊なビルド設定、外部jar、難読化、最適化、古いclassファイルなどでは、行番号情報がない場合があります。

その場合、次のようなメッセージに出会うことがあります。

Unable to install breakpoint due to missing line number attributes

この場合は、ビルド設定でデバッグ情報が含まれているか確認します。

ケース8:ライブラリやjarの中のコードを見ている

Eclipseでは、依存ライブラリのソースを開けることがあります。

たとえば、Spring Frameworkや外部ライブラリのクラスです。

しかし、ソースが表示されているからといって、必ずその場所に自由にブレークポイントを置けるとは限りません。

理由はいくつかあります。

原因内容
ソース添付だけで実行classと対応していない見ているソースと実行中classが完全一致しない
デバッグ情報がないjar行番号情報が不足している
別バージョンのソースを見ているjarのバージョンとソースのバージョンが違う
フレームワーク内部処理自分のアプリの流れとは違うタイミングで動く

新人エンジニアは、まず自分が書いたController、Service、DAOにブレークポイントを置いて確認してください。

Spring内部やライブラリ内部にいきなり入ると、かえって混乱しやすいです。

ケース9:同じクラス名が複数ある

プロジェクト内や依存関係に、同じようなクラス名が複数あると、違うファイルにブレークポイントを置いている可能性があります。

たとえば、次のようなケースです。

com.example.demo.controller.CarController
com.example.test.controller.CarController

または、古いパッケージと新しいパッケージの両方が残っている場合です。

確認項目見ること
package文実行中のControllerと同じパッケージか
URLマッピング本当にそのControllerが呼ばれるか
Consoleログどのクラスのログが出ているか
起動構成どのプロジェクトを起動しているか

名前が同じでも、パッケージが違えば別クラスです。

双子のように見えても、別人です。

片方に声をかけても、もう片方は反応しません。

ケース10:Spring Boot DevToolsや自動再起動で混乱している

Spring Boot DevToolsを使っている場合、コード変更時にアプリが自動再起動されることがあります。

便利な機能ですが、デバッグ時には次のような混乱が起きることがあります。

現象考えられること
ブレークポイントで止まらなくなった再起動後の状態とEclipseのデバッグ接続がずれている
修正が反映されたりされなかったりする自動ビルドや再起動タイミングが影響している
古い挙動が残っているアプリが完全停止していない

このような場合は、一度Spring Bootアプリを完全に停止します。

Consoleビューで赤い停止ボタンを押し、起動中のJavaプロセスが残っていないか確認します。

そのうえで、再度Debug Asで起動してください。

ケース11:ホットコード置換に失敗している

デバッグ中にJavaコードを修正すると、Eclipseが実行中のJVMへ変更を反映してくれる場合があります。

この機能は、Hot Code ReplaceやHotSwapのように呼ばれます。

しかし、すべての変更が反映できるわけではありません。

Eclipse JDT Debugは、Java VMをRunまたはDebugで起動したり、実行中のVMへ接続したり、VMが対応している場合に動的なクラス再読み込みを行う機能を持つと説明されています。

変更内容反映されやすさ
メソッド内の処理変更反映されやすい
文字列や条件式の変更反映されやすい
メソッド追加反映できないことがある
フィールド追加反映できないことがある
クラス構造の大きな変更反映できないことが多い

ホットコード置換に失敗しているのに、アプリを再起動していない場合、ブレークポイントの位置や実行コードが期待とずれることがあります。

迷ったら、再起動です。

開発中に困ったときの基本は、「保存、Clean、再ビルド、再Debug起動」です。

ケース12:ブレークポイントを置きたい場所がラムダ式やメソッドチェーンの途中

Javaのラムダ式やメソッドチェーンでは、見た目の1行に複数の処理が詰まっていることがあります。

carList.stream()
        .filter(car -> car.getPrice() >= 2000000)
        .map(car -> car.getName())
        .forEach(name -> System.out.println(name));




このようなコードでは、どこにブレークポイントを置くかによって止まり方がわかりにくくなる場合があります。

新人エンジニアのうちは、デバッグしやすいように一時的に分けて書くのもおすすめです。

for (CarDto car : carList) {

    if (car.getPrice() >= 2000000) {

        String name = car.getName();

        System.out.println(name);
    }
}




このように書くと、if文、getName、printlnの各行にブレークポイントを置きやすくなります。

かっこいいコードより、デバッグしやすいコードのほうが新人には大切な場面があります。

ケース13:匿名クラスや自動生成コードを見ている

Lombok、MapStruct、JPAのプロキシ、Springの自動生成クラスなどが絡むと、見えているソースと実際に動いているコードの関係がわかりにくくなることがあります。

たとえば、Lombokの@Getterや@Setterを使うと、ソースコード上にはgetterやsetterが見えません。

@Getter
@Setter
public class CarDto {

    private int carId;
    private String name;
    private int price;
}




実際にはコンパイル時にgetterやsetterが生成されます。

このような自動生成されたコードに対して、通常のJavaソースと同じ感覚でブレークポイントを置こうとすると混乱することがあります。

新人エンジニアの学習段階では、まずgetter、setterを手書きした普通のクラスでデバッグに慣れるのもよいです。

ケース14:リモートデバッグで接続先が違う

ローカルのSpring Bootではなく、Tomcat、Docker、別サーバー、リモートJVMに接続してデバッグしている場合があります。

このときは、Eclipseで開いているコードと、接続先で動いているコードが一致していないとブレークポイントが効きません。

確認項目内容
接続先本当に対象のJVMに接続しているか
デプロイ成果物最新のjarやwarが配置されているか
ソースバージョンEclipseのソースとサーバー上の成果物が同じか
ポート正しいデバッグポートにつないでいるか

リモートデバッグでは、「Eclipseで見ているもの」と「サーバーで動いているもの」が別物になりやすいです。

同じ教科書を見ているつもりでも、相手は旧版の教科書を読んでいるような状態です。

ケース15:Eclipseのワークスペースやプロジェクト設定が壊れている

頻度は高くありませんが、Eclipseのワークスペース設定やプロジェクト設定が不安定になっていることもあります。

たとえば、次のようなケースです。

状態起きること
プロジェクトのビルドパスが壊れている正しくコンパイルされない
Maven依存関係が壊れている実行classが不安定になる
ワークスペースのメタ情報が不整合表示やビルドが不自然になる
Eclipseプラグインが不安定ブレークポイント表示がおかしくなる

この場合は、次の順番で試します。

Project
Clean
Maven
Update Project
Eclipseを再起動
プロジェクトを再インポート

いきなりワークスペースを作り直す必要はありません。

まずは軽い対処から試しましょう。

新人エンジニア向けの確認手順

ブレークポイントが置けない、または効かないときは、次の順番で確認してください。

順番確認具体的な操作
1Debug起動しているかDebug As Spring Boot Appで起動
2Skip All BreakpointsがオフかBreakpointsビューを確認
3対象メソッドが呼ばれているかSystem.out.printlnで確認
4実行できる行に置いているかコメント行、空行、importを避ける
5ソースとclassが一致しているかClean、再ビルド、再起動
6別プロジェクトを動かしていないかConsoleと起動構成を確認
7デバッグ情報があるかコンパイラ設定やMaven設定を確認

この順番で見ると、かなりの問題は解決できます。

Spring BootのControllerで確認する例

たとえば、次のControllerにブレークポイントを置きたいとします。

@Controller
public class CarController {

    @GetMapping("/cars")
    public String list(Model model) {

        System.out.println("listメソッドに入りました");

        List<CarDto> carList = carsDao.findAll();

        model.addAttribute("carList", carList);

        return "cars/list";
    }
}




ブレークポイントを置くなら、次の行がよいです。

System.out.println("listメソッドに入りました");

または、次の行です。

List<CarDto> carList = carsDao.findAll();

もし止まらないなら、次を確認します。

確認内容
URL/cars にアクセスしているか
起動方法Debug Asで起動しているか
ログlistメソッドに入りました が出るか
Controller登録@Controllerが付いているか
プロジェクト編集しているプロジェクトを起動しているか

置けないのか、置けるが止まらないのかを分ける

ブレークポイントのトラブルでは、「置けない」と「止まらない」を分けることが大切です。

状態意味主な原因
置けない丸印自体が付かない行が実行対象でない、Javaエディタでない、Eclipse設定問題
置けるが止まらない丸印はあるが実行時に停止しないRun起動、処理未実行、全体無効、ソース不一致
止まるが位置が変期待と違う行で止まるソースとclassの不一致、古いビルド

この区別をしないと、調査が遠回りになります。

病院で「痛いです」だけでなく、「どこが、いつ、どのように痛いか」を伝える必要があるのと同じです。

ブレークポイントが効かないときにやってはいけないこと

焦って次のようなことをすると、余計に原因がわからなくなります。

やってはいけないこと理由
同じ場所に何度もブレークポイントを付け直す根本原因が別なら解決しない
関係ない設定を大量に変更する後で戻せなくなる
RunとDebugを混在させて複数起動するどのアプリが動いているかわからなくなる
ログを見ずに画面だけで判断するメソッドが呼ばれているか確認できない
古いサーバープロセスを放置する修正前のアプリが動き続ける

ブレークポイントが効かないときほど、落ち着いて1つずつ確認しましょう。

デバッグの問題も、デバッグする必要があります!

おすすめの復旧手順

どうしても原因がわからないときは、次の手順で復旧を試してください。

1. Spring Bootアプリを完全に停止する
2. BreakpointsビューでSkip All Breakpointsを確認する
3. Project > Clean を実行する
4. Maven > Update Project を実行する
5. Eclipseを再起動する
6. 対象Controllerの先頭にSystem.out.printlnを入れる
7. Debug As > Spring Boot Appで起動する
8. 正しいURLへアクセスする

この手順は、地味ですがかなり有効です。

特に、古いclassや古い起動プロセスが原因の場合、停止とCleanと再Debug起動で直ることが多いです。

まとめ

Eclipse上のJavaコードでブレークポイントを置けるはずが置けない、または置いても止まらない場合、原因は1つではありません。

主に、Eclipseのブレークポイント設定、起動方法、実行されるコード、ソースとclassの対応、コンパイル時のデバッグ情報を確認します。

原因確認すること
Run起動しているDebug Asで起動する
Skip All Breakpointsが有効Breakpointsビューで無効化を解除する
処理が呼ばれていないURL、GET/POST、ログを確認する
実行されない行に置いているコメント、空行、importを避ける
ソースとclassがずれているClean、再ビルド、再起動する
デバッグ情報がないコンパイラやMaven/Gradle設定を確認する
別プロジェクトを起動しているConsoleと起動構成を見る

一言でまとめるなら、ブレークポイントは「Eclipseに丸を付ける機能」ではなく、「実行中のJVMとソースコードの行を対応させて止める仕組み」です。

そのため、Debug起動、実行行、ソースとclassの一致、ブレークポイントの有効状態がそろって初めて正しく動きます。

新人エンジニアは、まず「Debugで起動しているか」「そのメソッドに本当に入っているか」「Skip All Breakpointsがオンになっていないか」の3つを確認してください。

今後の学習では、EclipseのDebugパースペクティブ、Breakpointsビュー、Variablesビュー、Consoleビュー、Project Clean、Maven Update、Spring Bootの起動構成を順番に学ぶとよいです。ブレークポイントが効かないときも、慌てずに原因を切り分ける力を身につけましょう!

セイ・コンサルティング・グループでは新人エンジニア研修のアシスタント講師を募集しています。

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。

学生時代は趣味と実益を兼ねてリゾートバイトにいそしむ。長野県白馬村に始まり、志賀高原でのスキーインストラクター、沖縄石垣島、北海道トマム。高じてオーストラリアのゴールドコーストでツアーガイドなど。現在は野菜作りにはまっている。