こんにちは、かつコーチです。
バグの原因を探すときに、System.out.println()を大量に埋め込んでは消す、を繰り返していませんか。
今回は、IntelliJ IDEAを例に、デバッガ(プログラムを一時停止させながら内部状態を確認できるツール)を使った効率的な原因調査の方法を解説します。
デバッガとは?println頼みから卒業する
printデバッグの限界
System.out.println()によるデバッグは手軽ですが、確認したい変数が増えるたびにコードを書き換える必要があり、確認後は消し忘れがコードに残るリスクもあります。
// printデバッグの例:確認のたびにコードを書き換える必要がある
public int calculateDiscount(int price, int rank) {
System.out.println("price = " + price); // デバッグ用
System.out.println("rank = " + rank); // デバッグ用
int discount = price * rank / 100;
System.out.println("discount = " + discount); // デバッグ用
return discount;
}
デバッガを使えば、コードを1行も書き換えずに、実行中の変数の値をその場で確認できます。
ブレークポイントとは
ブレークポイントとは、プログラムの実行を一時停止させたい行に設定する印のことです。
IntelliJ IDEAでは、行番号の左側の余白をクリックすると赤い丸が表示され、そこがブレークポイントになります。
ブレークポイントを使ったデバッグの基本手順
手順1:ブレークポイントを設置する
原因を疑っている行、またはその処理の入口となる行にブレークポイントを設置します。
public int calculateDiscount(int price, int rank) {
int discount = price * rank / 100; // ← この行にブレークポイントを設置
return discount;
}
手順2:デバッグ実行する
通常の実行ボタン(▶)ではなく、虫のアイコンの「Debug」ボタンから実行します。
ブレークポイントに到達すると、その行の実行直前でプログラムが一時停止します。
手順3:変数の値を確認する
一時停止すると、画面下部の「Variables」(変数)ペインに、その時点でのローカル変数やフィールドの値が一覧表示されます。priceが想定と違う値になっていないか、rankが0になっていないかなど、コードを書き換えずにその場で確認できます。
手順4:ステップ実行で1行ずつ進める
- Step Over(F8):現在行を実行し、次の行へ進む(メソッド呼び出しの中には入らない)
- Step Into(F7):呼び出し先のメソッドの中に入って追跡する
- Resume Program(F9):次のブレークポイントまで再開する
この3つを使い分けることで、「どの行で値がおかしくなったか」をピンポイントで特定できます。
つまずいたポイント:条件付きブレークポイントで救われた話
ループの1000回目だけ発生する不具合を調査していたとき、通常のブレークポイントでは999回も無関係な停止を繰り返す羽目になりました。
// ❌そのまま:ループの先頭にブレークポイントを置くと999回も無駄に止まる
for (int i = 0; i < 10000; i++) {
Order order = orders.get(i);
processOrder(order); // 特定のiだけで例外が起きる
}
このとき実際に表示されていたエラーは次のようなものでした。
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
Index 1000 out of bounds for length 1000
at Main.processOrder(Main.java:15)
at Main.main(Main.java:8)
原因を探すために、IntelliJ IDEAのブレークポイントを右クリックして条件付きブレークポイントを設定しました。
条件: i == 999
こうすることで、iが999のときだけプログラムが一時停止し、無駄な停止を繰り返さずに原因の変数状態にすぐたどり着けました。
原因は、配列の範囲外を1件多く読み込もうとする境界値の誤りでした。
数百回・数千回のループの特定の回だけで起きる不具合こそ、条件付きブレークポイントの本領が発揮される場面です。
例外発生時に自動で止めるブレークポイント
例外ブレークポイントの設定
「いつ例外が発生するか分からないが、発生した瞬間の状態を見たい」という場合は、例外ブレークポイントが便利です。
IntelliJ IDEAでは「Run」メニューの「View Breakpoints」から、対象の例外クラス(例:NullPointerException)を指定して例外発生時に自動停止させる設定ができます。
これを使うと、スタックトレースを読むだけでは分かりにくい「例外発生直前の各変数の値」を直接確認でき、原因特定のスピードが大きく上がります。
まとめ
この記事のポイント
- printデバッグはコードの書き換えが必要で消し忘れのリスクもある
- ブレークポイントを使えばコードを変えずに実行中の変数を確認できる
- Step Over・Step Into・Resumeを使い分けて原因の行を絞り込む
- 特定条件下でのみ発生する不具合は条件付きブレークポイントが有効
- 例外ブレークポイントを使えば例外発生の瞬間の状態を確認できる
次に読むべき記事
- スタックトレースの読み方の基礎は「よくあるコンパイルエラーの読み方」の記事へ
- 発生しやすい実行時エラーの代表例は「NullPointerExceptionの防ぎ方」の記事へ
タグ: Java, 初心者向け, エラー解決