1. はじめに
Stack Trace(スタックトレース)は、エラー(例外)が発生する直前までにあなたのプログラムで呼び出されたメソッドの一覧です。プログラムで例外が発生すると、Java は自動的にスタックトレースを画面に出力します。これは「雪の上の足跡」のようなもので、エラーに至るまでにプログラムがたどった手順が分かります。
アナロジー:
迷路を歩いていて、突然壁に突き当たったと想像してください。Stack trace は、迷子になる前にどの通路を歩いてきたのかを示す地図です。
Stack Trace はどのように表示されるか?
プログラムでエラーが発生すると、Java はおおよそ次のようなメッセージを出力します:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.divide(Main.java:10)
at Main.main(Main.java:5)
ここには何が書かれている?
- Exception in thread "main" — エラーが発生したスレッド名(通常は "main")。
- java.lang.ArithmeticException: / by zero — 例外の種類とそのメッセージ。
- at Main.divide(Main.java:10) — クラス Main のメソッド divide、行番号 10。
- at Main.main(Main.java:5) — クラス Main のメソッド main、行番号 5。
各行の at ... はスタックの一段(スタックフレーム)を表します。一番上の行がエラーが発生した場所です。その下には、それを呼び出したメソッドが続き、プログラムの開始地点までたどれます。
2. スタックトレースの読み方
ステップ1. 例外の種類とメッセージを確認する
最初の行には常にエラーの種類とその説明が含まれます:
java.lang.ArithmeticException: / by zero
これだけでヒントになります。エラーは 0 による除算に関連しています。
ステップ2. 最初の「at ...」行を見る
ここが実際にエラーが発生した場所です:
at Main.divide(Main.java:10)
つまり、クラス Main のメソッド divide の 10 行目でエラーが発生しました。
ステップ3. スタックを上へたどる
次の行は、そのメソッドを呼び出した側を示します:
at Main.main(Main.java:5)
つまり、メソッド main が divide を呼び出し、エラーは上位へ「伝播」しました。行番号は 5 です。
ステップ4. 自分のクラスを探す
長いスタックトレースには、しばしば標準ライブラリ(例: java.util、java.io)のメソッドが含まれます。
あなたのクラスはたいてい先頭付近にあります。 クラス名やファイル名を見て、自分のコードを探しましょう。
3. 例: 実際のスタックトレースを読み解く
コード:
public class Main
{
public static void main(String[] args)
{
int result = divide(10, 0);
System.out.println("結果: " + result);
}
public static int divide(int a, int b)
{
return a / b;
}
}
エラー:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.divide(Main.java:8)
at Main.main(Main.java:3)
解説:
- エラー: 0 での除算(ArithmeticException)。
- 発生箇所はメソッド divide の 8 行目。
- 呼び出し元はメソッド main の 3 行目。
どうする?
ファイル Main.java を開き、8 行目を確認します。0 で割っている箇所が見つかるので、修正しましょう。
4. 複数メソッドにまたがるスタックトレース
コード:
public class Main
{
public static void main(String[] args)
{
process();
}
public static void process()
{
calculate();
}
public static void calculate()
{
int[] arr = {1, 2, 3};
System.out.println(arr[10]); // エラー!
}
}
エラー:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3
at Main.calculate(Main.java:11)
at Main.process(Main.java:7)
at Main.main(Main.java:3)
解説:
- エラー: 配列の範囲外アクセス(ArrayIndexOutOfBoundsException)。
- calculate で発生(11 行目)。
- process から呼び出し(7 行目)。
- main から呼び出し(3 行目)。
結論:
スタックトレースは、プログラムがエラーに至るまでの経路全体を示してくれます。
5. スタックトレースでよくある誤り
誤り1: スタックトレースを無視する。
初心者はしばしば「赤いエラー」だけを見て、スタックトレースを読みません。そうしないでください! Stack trace は、バグの所在を示すヒントです。
誤り2: 例外メッセージの行と、発生箇所の行を混同する。
重要: 最初の行はエラーの種類であり、発生箇所は最初の at ... の行にあります。
誤り3: システムクラスの中に原因を探してしまう。
at java.base/java.util.Scanner.nextInt(Scanner.java:123) のような行が見えても、すぐに Java のソースを読みに行く必要はありません。自分のコードでそのメソッドをどこから呼んだかを確認しましょう。
誤り4: 行番号を活用しない。
行番号は最強の味方です。ファイルを開き、該当の行を見つければ、問題が見えてきます。
誤り5: スタックトレースが「経路」であることを理解していない。
スタックトレースは、プログラムがどのようにしてエラーに至ったかを示します。ときには、一番上の行ではなく、メソッドの呼び出し方に原因がある場合もあります。
GO TO FULL VERSION