スタックトレース(stack trace)

処理の呼び出し履歴だよ
エラー発生までに、どの関数(メソッド)をどこで呼び出したかが表示されるよ
簡単に書くよ
スタックトレース(stack trace)とは
エラーが発生したときに表示される内容で、そのエラーが発生するまでの過程(どんな処理がどの順番で呼び出されたかの流れ)を、ざっくりと表示したもの
です。

詳しく書くよ
プログラミングのお話です。
プログラムを実行しました。
エラーが発生しました。
処理が中断しました。
そのときに表示される内容で
エラーが発生するまでに、どんな処理を、どの順番で呼び出したか表現したもの
が「スタックトレース」です。
メモリのスタック領域の内容が表示されているのでスタックトレースと言いますが、気にする必要はありません。
Javaを例に説明しましょう。
例えば、以下のようなJavaで書いたプログラムがあったとします。
public class test01 {
public static void func01(){
func02();
}
public static void func02(){
func03();
}
public static void func03(){
//Exception発生
Integer a=10/0;
}
public static void main(String[] args){
func01();
}
}
分かりやすくするために、行番号を振っておきますね。
01public class test01 {
02 public static void func01(){
03 func02();
04 }
05
06 public static void func02(){
07 func03();
08 }
09
10 public static void func03(){
11 //Exception発生
12 Integer a=10/0;
13 }
14
15 public static void main(String[] args){
16 func01();
17 }
18}
このプログラムで最初に呼び出されるのは、15行目から始まる
15 public static void main(String[] args){
16 func01();
17 }
の部分です。
Javaのプログラムは(Java以外も大概はそうですが)「main」から処理が始まるのです。
さて、15行目から始まった処理ですが、16行目の
16 func01();
のところで「func01()」というメソッド(関数みたいなもの)が呼び出されました。
そこで処理は、2行目から始まる
02 public static void func01(){
03 func02();
04 }
に移動します。
さらに、このタイミングで
1.main()の中にある16行目から飛びましたわ
という内容が、メモリのスタック領域という場所に書き込まれます。
処理は進んで、次に3行目の
03 func02();
のところでメソッド「func02()」が呼び出されました。
そこで処理は、6行目から始まる
06 public static void func02(){
07 func03();
08 }
に移動します。
このタイミングで、先程と同じように
2.func01()の中にある3行目から飛びましたわ
という内容が、メモリのスタック領域という場所に書き込まれます。
注意点として、今回の内容は先程の内容に上積みされます。
つまり、実際には
2.func01()の中にある3行目から飛びましたわ
1.main()の中にある16行目から飛びましたわ
の形になります。
後から来たのが上に乗っかりますからね。
さらに処理は進んで、7行目の
07 func03();
のところでメソッド「func03」が呼ばれました。
そこで処理は、10行目から始まる
10 public static void func03(){
11 //Exception発生
12 Integer a=10/0;
13 }
に移動します。
このタイミングで、先程と同じように
3.func02()の中にある7行目から飛びましたわ
という内容が、メモリのスタック領域という場所に書き込まれます。
先程同様、実際には
3.func02()の中にある7行目から飛びましたわ
2.func01()の中にある3行目から飛びましたわ
1.main()の中にある16行目から飛びましたわ
の形になります。
さぁ、いよいよ佳境です。
12行目の処理
12 Integer a=10/0;
でエラーになります。
この処理は「10を0で割って、結果を『a』という箱に入れる」処理です。
0で割ることはできませんからね。
この12行目の処理が実行された時点で、エラーになります。
このタイミングで、メモリのスタック領域に
4.func03()の中にある12行目でエラーになりましたわ
という内容が、メモリのスタック領域という場所に書き込まれます。
先程同様、実際には
4.func03()の中にある12行目でエラーになりましたわ
3.func02()の中にある7行目から飛びましたわ
2.func01()の中にある3行目から飛びましたわ
1.main()の中にある16行目から飛びましたわ
の形になります。
そして、エラー発生時のスタック領域の内容、つまり
4.func03()の中にある12行目でエラーになりましたわ
3.func02()の中にある7行目から飛びましたわ
2.func01()の中にある3行目から飛びましたわ
1.main()の中にある16行目から飛びましたわ
を表示したのが、スタックトレースです。
実際のスタックトレースは、例えば以下のような内容です。
Exception in thread "main" java.lang.ArithmeticException: / by zero
at test01.func03(test01.java:12)
at test01.func02(test01.java:7)
at test01.func01(test01.java:3)
at test01.main(test01.java:16)
これにも行番号を振ってみましょう。
01Exception in thread "main" java.lang.ArithmeticException: / by zero
02 at test01.func03(test01.java:12)
03 at test01.func02(test01.java:7)
04 at test01.func01(test01.java:3)
05 at test01.main(test01.java:16)
まずは1行目の
01Exception in thread "main" java.lang.ArithmeticException: / by zero
に注目してください。
これは、要約すると
『java.lang.ArithmeticException: / by zero』ってエラーが発生したよ
と言っています。
次に2行目の
02 at test01.func03(test01.java:12)
を見てみましょう。
これは
func03()の中(「test01.java」の12行目)から飛んだよ(エラーになったよ)
という内容です。
同様に、3行目の
03 at test01.func02(test01.java:7)
は
func02()の中(「test01.java」の7行目)から飛んだよ
の意味ですし、4行目の
04 at test01.func01(test01.java:3)
は
func01()の中(「test01.java」の3行目)から飛んだよ
の意味ですし、5行目の
05 at test01.main(test01.java:16)
は
main()の中(「test01.java」の16行目)から飛んだよ
の意味です。
まとめると
『java.lang.ArithmeticException: / by zero』ってエラーが発生したよ
func03()の中(「test01.java」の12行目)から飛んだよ(エラーになったよ)
func02()の中(「test01.java」の7行目)から飛んだよ
func01()の中(「test01.java」の3行目)から飛んだよ
main()の中(「test01.java」の16行目)から飛んだよ
になります。
さらに、もうひとつ覚えておきましょう。
main()の中(「test01.java」の16行目)から飛んだよ
と書いてありますが、main()の中から一体どこに飛んだのでしょうね。
それは1つ上の
func01()の中(「test01.java」の3行目)から飛んだよ
を見れば分かります。
次は「func01()」からどこかへ飛んだのです。
ということは、そのひとつ前は「func01()」に飛んだことが分かります。
よって
func01()の中(「test01.java」の3行目)から飛んだよ
main()の中(「test01.java」の16行目)から飛んだよ
の2行を同時に見ることによって
main()の中(「test01.java」の16行目)から飛んだよ
は
main()の中(「test01.java」の16行目)から「func01()に」飛んだよ
と読み替えることができます。
同じ要領で、このスタックトレース全体を読み解くと
1.まず、main()が実行された
2.「test01.java」の16行目でmain()からfunc01()に移動した
3.「test01.java」の3行目でfunc01()からfunc02()に移動した
4.「test01.java」の7行目でfunc02()からfunc03()に移動した
5.「test01.java」の12行目でエラーになった
6.エラーの内容は「java.lang.ArithmeticException: / by zero」である
ということが分かります。
実際の処理の順番とスタックトレースの並び順が逆になっているので分かりにくいかもしれませんが、慣れればきっと読み解けるはずです。
この時点で「あれ?なんでこんな処理が動いているの?」となる場合もありますよね。
少なくとも、どのような順番でどのような処理(メソッド、関数)を呼び出したのかは把握することができます。
このように、スタックトレースは、エラー発生時の調査の助けとなる情報です。
パッと見では、ごちゃごちゃしていて読みにくく感じるかもしれませんが、頑張って解読できるようになってあげてください。

一言でまとめるよ
まぁ「スタックトレース」って単語が出てきたら「エラー発生時点までの処理の呼び出し履歴なんだな~」と、お考えください。

おまけ
■訳してみるよ
「stack(スタック)」の意味は「(物を積み重ねた)山」とか「干し草の山」とか「積み重ね」とかです。
「trace(トレース)」の意味は「跡」とか「痕跡」とか「たどる」とか「追跡する」とかです。
何となくくっつけると
積み重ね痕跡
となります。