ブレークポイントの全体像
ブレークポイントは「この行で一度、必ず止まって中身を観測する」ための印(デバッグの要」です。IDE(IntelliJ IDEA、Eclipse、VS Code など)で指定した行に到達するとプログラムが一時停止し、その瞬間の変数や式の値、分岐の選択、例外の原因を安全に確認できます。思い込みではなく「事実の状態」を見るための最短ルートで、ステップ実行や変数ウォッチと組み合わせると原因特定が劇的に速くなります。
どこに置くかと止め方の基本
問題の直前に置く
止める位置は「症状が出る直前」が基本です。例外が起きる行、分岐に入る直前、ループの本文の先頭に置けば、前後の差分が明確になります。
int[] a = {10, 20, 30};
for (int i = 0; i <= a.length; i++) { // バグの疑い:<=
System.out.println(a[i]); // ← ここにブレークポイント
}
Java停止時に i と a.length を観測し、最後の周回で範囲外アクセスが起きる事実(i == a.length)を確認できます。
入口・出口を押さえる
メソッドの「入口」と「出口(戻り値)」で止めると、入力→処理→出力の整合性を素早く検証できます。疑わしいメソッドは入口でイン、出口でアウトという二点止めが効率的です。
static int taxed(int subtotal, double rate) {
// 入口で止めて引数を観測
int tax = (int) Math.round(subtotal * rate);
int total = subtotal + tax;
return total; // ここで止めて戻り値を観測
}
Java種類と使い分け(重要ポイントの深掘り)
行ブレークポイント(最も基本)
指定したソース行で停止します。ほぼすべての IDE が対応し、条件やログなどの拡張が設定できます。まずはこれが基盤です。
条件付きブレークポイント(必要な時だけ止める)
大量データの中で「特定のケースだけ」停止したい時に使います。条件式が true の時のみ止まるため、ノイズを消して原因に集中できます。
for (String id : ids) {
process(id); // 条件:id.equals("X-999") の時だけ停止
}
Java条件例:id.equals("X-999")、i == a.length - 1、user != null && user.isActive()。
ヒットカウント・フィルタ(境界観測に有効)
「100回目で止める」「特定スレッドでのみ止める」といった設定で、ループ境界や並行文脈をピンポイント観測できます。境界バグの再現に強いです。
例外ブレークポイント(投げられた瞬間に止める)
特定の例外(NullPointerException、IndexOutOfBoundsException など)が「投げられた瞬間」に停止します。スタックトレースの原因行に一撃で辿り、直前の値をその場で確認できます。IDEの「Exception Breakpoints」に設定します。
メソッド/関数ブレークポイント(入口で必ず止める)
特定メソッドの「呼び出し時」に止まります。ユーティリティやライブラリ呼び出しの挙動を見たいときに便利です。ただし内部まで潜りすぎないよう、ステップアウトとセットで使いましょう。
フィールド/監視ブレークポイント(値の変更で止める)
特定フィールドが「書き換えられた瞬間」に停止します。いつ・誰が・どの値に更新したかを捕まえやすく、謎の値の揺れや不正な再代入を特定できます。
ログポイントと副作用回避
ログポイント(止めずに事実だけ記録)
「停止せず」「コンソールに値を出す」設定です。本番相当の長い処理で、流れを壊さずに観測したい場合に有効です。IntelliJ ならブレークポイントのプロパティで「Log message to console」「Disable suspending」を選びます。
[log] id=X-999 state=INIT counter=42
停止しないため、並行処理でもタイミングの影響が少なくなります。
副作用のある評価は避ける
停止中にウォッチや評価で「状態を進める」「外部へアクセスする」式を実行すると再現性が崩れます。iterator.next()、I/O、DB 呼び出しなどは評価しない。観測は「読み取りのみ」に徹しましょう。
ステップ実行・ウォッチとの連携
止めて、1行進めて、差分を見る
ブレークポイントで止めたら、ステップオーバーで行を実行し、前後の変数・戻り値の差を確認します。分岐前後、更新前後、戻り値直前が黄金ポイントです。
boolean hasText = s != null && !s.isBlank(); // ここで止めて hasText を観測
if (hasText) submit(); // 1行進めてどちらへ進むかを見る
Javaウォッチで「なぜ」を可視化
停止中に list.size(), map.containsKey(key), Objects.equals(a,b), i < a.length のような式をウォッチし、意図と一致しているかを確認します。値の変化と論理の真偽が揃うと、原因が浮き上がります。
よくあるつまずきと対策
潜りすぎて迷子になる
無闇なステップインでライブラリ内部に入り込むと、時間を浪費します。怪しいメソッドだけインし、不要ならステップアウト。必要に応じてブレークポイントを「目的地の直前」に移動して再開します。
並行処理で値が揺れる
複数スレッドが動くと停止中に他スレッドが更新し、状態が変わります。スレッド名やIDでフィルタ、ロック取得中に観測、シングルスレッド環境での再現コードを作る——この順で安定させます。
止める位置が遠すぎる
症状から離れた場所で止めても有効な差分が得られません。例外行の直前、分岐の直前、ループの本文先頭、メソッドの入口・出口に「近接配置」するのが鉄則です。
例題で身につける
例 1: 文字列正規化の分岐を検証
static String normalize(String s) {
if (s == null || s.isBlank()) return "";
return s.trim().toUpperCase();
}
Javaif の行にブレークポイント。停止時に s == null と s.isBlank() をウォッチし、短絡評価でどちらが判定されているかを確認。次行でどちらの枝へ進んだかをステップで確定します。
例 2: 例外ブレークポイントで NPE の瞬間を捕まえる
String s = null;
int len = s.length(); // NPE
JavaNullPointerException のブレークポイントを設定すると、投げられた瞬間に止まります。s が null である事実を即確認し、入口に Objects.requireNonNull(s, "...") を追加する修正へ直行できます。
例 3: フィールド更新の犯人特定
class Counter {
int value;
void add(int d) { value += d; }
void reset() { value = 0; }
}
Javavalue にフィールドブレークポイントを設定。どのメソッド・どのスレッドが何の値に更新したかを停止時に確認でき、意図しない reset 呼び出しの場所を特定できます。
仕上げのアドバイス(重要部分のまとめ)
ブレークポイントは「問題直前で止めて事実を観測する」ための最強の道具です。行ブレークポイントを基盤に、条件付き・ヒットカウント・例外・フィールドを使い分ける。止める位置は近接配置、ステップ実行で差分を確認、ウォッチで論理の真偽を可視化。副作用のある評価は避け、必要ならログポイントで非停止観測に切り替える——この型を身につけると、原因特定の道筋が短く、確実になります。
