はじめに
プログラムを書いていると、避けて通れないのがエラーです。Javaでは、エラーが発生すると「スタックトレース」と呼ばれるメッセージが出力されます。これには、エラーの種類や発生箇所、プログラム内での流れが記録されており、問題を解決するための重要な手がかりになります。
しかし、スタックトレースやエラーログは初心者にとっては難しく見えるものです。「どこから読めばいいの?」「何を見れば原因がわかるの?」と感じる人も多いでしょう。
本記事では、初心者の方を対象に、スタックトレースやエラーログの基本的な読み方をわかりやすく解説します。以下の2つのポイントを押さえることで、エラー発生箇所を特定し、原因を効率よく辿る方法を学びましょう。
- スタックトレースは発生元から順に積み上がった結果がそのまま出力される。
- 発生元から発生先に辿ることで、エラーの根本原因を特定できる。
スタックトレースそのものの詳細な構造については深く掘り下げませんが、必要最低限の知識は解説します。また練習問題を通じて、エラーと向き合い、自信を持って原因を特定できる力を身につけましょう!
スタックトレースとエラーログの違い

エラーの解析を行う際に、スタックトレースとエラーログの違いを理解しておくことは非常に重要です。それぞれの役割を簡単に説明します。
スタックトレース
概要
スタックトレースは、エラーが発生した際にJavaが自動的に出力する「メソッド呼び出しの履歴」です。プログラムがどのように実行され、どのメソッドでエラーが発生したのかを順を追って記録しています。
スタックというのは「積み上げる」という意味です。エラーとなった呼び元から順に積みあがってそのまま出力されるので、一番下が発生元で一番上が発生先(実際の発生個所)です。
主な特徴
- エラーの種類(例:
NullPointerException
やArrayIndexOutOfBoundsException
など)が明記される。 - エラー発生時点のコード位置が特定できる(例: クラス名と行番号)。
- 発生元から順に辿ることでエラーの伝播経路を追える。
コード例
1 2 3 4 5 6 7 |
java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null at Example.methodC(Example.java:16) // 発生先 at Example.methodB(Example.java:12) at Example.methodA(Example.java:8) at Example.main(Example.java:4) // 発生元 |
エラーログ
概要
エラーログは、アプリケーションが開発者や運用者に向けて出力するメッセージ全般を指します。これには、スタックトレースも含まれますが、他にも警告や情報メッセージが含まれることがあります。
主な特徴
- アプリケーションの挙動や状態を記録するものも含まれる。
- カスタマイズ可能で、独自のメッセージを追加することができる。
- スタックトレース以外の詳細(例: エラー発生時の変数値、タイムスタンプ、ログレベルなど)を含む場合がある。
コード例
1 2 3 4 5 6 7 8 9 |
[INFO] 2025-01-15 12:00:00 - Starting application... [ERROR] 2025-01-15 12:01:00 - An error occurred in methodC java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null at Example.methodC(Example.java:16) at Example.methodB(Example.java:12) at Example.methodA(Example.java:8) at Example.main(Example.java:4) |
違いを整理
項目 | スタックトレース | エラーログ |
---|---|---|
定義 | メソッド呼び出しの履歴とエラー発生箇所の記録。 | アプリケーションが出力するメッセージ全般。 |
内容 | 主にエラー情報(例: 例外の種類、発生箇所)。 | スタックトレースを含む任意のログ情報。 |
出力元 | Javaランタイム環境によって自動生成。 | 開発者が設計・実装で自由に制御可能。 |
用途 | エラー発生箇所の特定とメソッドの呼び出し関係の追跡。 | アプリケーション全体の状態やエラー情報の記録。 |
スタックトレースを読むための2つのポイント

スタックトレースを効率よく読み解くためには、以下の2つのポイントを押さえることが重要です。それぞれのポイントを具体例とともに解説します。
ポイント1:発生元を確認する
スタックトレースは、プログラムがエラーをスローした時点からメソッドの呼び出し履歴を積み上げたもの出力します。そのため、最も下に記載されているのがエラーの発生元です。
コード例
1 2 3 4 5 6 7 |
java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null at Example.methodC(Example.java:16) at Example.methodB(Example.java:12) at Example.methodA(Example.java:8) at Example.main(Example.java:4) // 発生元 |
読み方
- 最下部にある
Example.main(Example.java:4)
がエラーの発生元です。 - エラーの発生先は 最後のスタックトレース行、この場合は
Example.methodC(Example.java:16)
です。 - エラー内容 (
NullPointerException
) と発生した行番号 (16
) に注目することで、問題の箇所が特定できます。
ポイント2:上へ辿る
エラーの発生元がわかったらスタックトレースを上に辿り、エラーが伝播していった経路を確認します。これにより、エラーの根本原因を特定できます。
呼び出し履歴の解析
ポイント1のコード例にあるスタックトレースの流れを見ると、以下の順でメソッドが呼び出されていることがわかります。
main
メソッドがmethodA
を呼び出し。methodA
がmethodB
を呼び出し。methodB
がmethodC
を呼び出し、ここでエラーが発生。
原因の追跡
methodC
を確認すると、NullPointerException
が発生しています。methodC
内のコードでnull
の値を操作しようとした部分を見つけ、修正します。
コード例
1 2 3 4 5 6 |
private static void methodC() { String str = null; // この値が null System.out.println(str.length()); // ここでエラー発生 } |
練習問題

以下のサンプルコードとスタックトレースを参考にして、エラーの原因箇所を特定してみましょう。
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class DebugPractice { public static void main(String[] args) { try { startProgram(); } catch (Exception e) { e.printStackTrace(); } } private static void startProgram() { calculateValue(); } private static void calculateValue() { divide(10, 0); } private static int divide(int a, int b) { return a / b; // 分母がゼロの場合にエラーが発生 } } |
実行時のスタックトレース
プログラムを実行すると、次のようなスタックトレースが表示されます。
1 2 3 4 5 6 7 |
java.lang.ArithmeticException: / by zero at DebugPractice.divide(DebugPractice.java:19) at DebugPractice.calculateValue(DebugPractice.java:15) at DebugPractice.startProgram(DebugPractice.java:11) at DebugPractice.main(DebugPractice.java:4) |
問題
- このエラーの種類は何ですか?
- どの行でエラーが発生しましたか?
- エラーの原因をコードの具体的な箇所から説明してください。
解答例と解説
- このエラーの種類は何ですか?
- エラーの種類は
ArithmeticException
です。 / by zero
というメッセージが示す通り、ゼロで割り算を試みた際に発生する例外です。
- エラーの種類は
- どの行でエラーが発生しましたか?
- スタックトレースの一番下を見ると、エラーは次の箇所で発生しています。
at DebugPractice.divide(DebugPractice.java:19)
DebugPractice
クラスのdivide
メソッド内、19行目でエラーが発生しています。
- エラーの原因をコードの具体的な箇所から説明してください。
- 該当するコードは次の部分です。
return a / b; // 分母がゼロの場合にエラーが発生
b
の値が0
になっているため、ゼロで割り算を試みたことがエラーの原因です。
エラーの伝播経路
スタックトレースを発生元から確認すると、以下の順でメソッドが呼び出されていることがわかります
main
メソッドがstartProgram
を呼び出す。startProgram
がcalculateValue
を呼び出す。calculateValue
がdivide
を呼び出し、ここでエラーが発生。
修正方法
ゼロで割り算を行わないようにするため、divide
メソッドに分母がゼロかどうかを確認する処理を追加します。
修正版コード
1 2 3 4 5 6 7 8 |
private static int divide(int a, int b) { if (b == 0) { throw new IllegalArgumentException("分母がゼロです"); } return a / b; } |
エラーログが以下のように出力され、意図しない操作をしたことが分かるようになりました。
1 2 3 4 5 6 7 |
java.lang.IllegalArgumentException: 分母がゼロです at DebugPractice.divide(DebugPractice.java:20) at DebugPractice.calculateValue(DebugPractice.java:15) at DebugPractice.startProgram(DebugPractice.java:11) at DebugPractice.main(DebugPractice.java:4) |
まとめ
Javaプログラムの開発中に発生するエラーは、初心者にとって悩みの種になりがちです。しかし、スタックトレースやエラーログを正しく読み解くスキルを身につけることで、問題解決のスピードが格段に向上します。本記事では、初心者がエラーログを活用するための基本的な考え方とポイントを解説しました。
本記事で学んだポイント
- スタックトレースとエラーログの違い
- スタックトレースはエラー発生時のメソッド呼び出し履歴を示し、エラーログはプログラムの挙動や状態全般を記録します。エラーログはプログラマ自身で制御できるので、意図しない操作による結果をわかりやすくできます。
- スタックトレースを読む2つのポイント
- 発生元を確認する:スタックトレースの一番下に記載された行が発生元です。
- 発生元から辿る:発生元から上に辿り、エラーがどのように伝播してきたのかを確認します。
- 練習問題で実践
- 実際のスタックトレースとコードを使って、エラー発生箇所を特定する練習を行いました。エラー内容を正確に理解し、原因に対応するための修正方法を学びました。
次のアクション
スタックトレースを正しく読むスキルは、エラー解析の第一歩です。このスキルをさらに活用するために、以下の方法も試してみましょう。
- ログ出力を工夫する:エラー発生時の変数値や状態を記録することで、より効率的なデバッグが可能になります。
- デバッグツールを活用する:IDEに搭載されたデバッグ機能を使えば、エラーの発生箇所や実行中の変数の値を簡単に確認できます。
コメント