JavaでThrowableオブジェクトでコールスタックを出力することができます。 現在のコードの位置まで任意の関数を経てきたのかを示すことをStack traceと呼ばれます。
Throwableの次のメソッドを使用して、Traceを取得または出力することができます。
// Throwable.java
public void printStackTrace()
public void printStackTrace(PrintStream s)
public StackTraceElement[] getStackTrace()
Javaコードを見ると、ExceptionクラスはThrowableクラスを継承します。 そのため、ExceptionオブジェクトもThrowableのメソッドを利用することができます。
public class Exception extends Throwable {
...
}
Stack trace出力
通常try-catchパターンで例外処理をします。
ここで Exception.printStackTrace()
を呼び出すと、ログにStack traceが出力されます。
try {
Exception e = new Exception();
e.initCause(new IOException("No space memory"));
throw e;
} catch(Exception e) {
e.printStackTrace();
}
結果
java.lang.Exception
at example.StackTrace$AAA.ccc(StackTrace.java:21)
at example.StackTrace$AAA.bbb(StackTrace.java:14)
at example.StackTrace$AAA.aaa(StackTrace.java:10)
at example.StackTrace.main(StackTrace.java:47)
Caused by: java.io.IOException: No space memory
at example.StackTrace$AAA.ccc(StackTrace.java:22)
... 3 more
Throwableは printStackTrace(PrintWriter s)
メソッドもサポートします。
次のようにPrintWriterを引数として渡してTraceをPrintWriterに追加することができます。
try {
Exception e = new Exception();
e.initCause(new IOException("No space memory"));
throw e;
} catch(Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.append("+++Start printing trace:\n");
e.printStackTrace(pw);
pw.append("---Finish printing trace");
System.out.println(sw.toString());
}
結果
+++Start printing trace:
java.lang.Exception
at example.StackTrace$AAA.fff(StackTrace.java:50)
at example.StackTrace$AAA.bbb(StackTrace.java:22)
at example.StackTrace$AAA.aaa(StackTrace.java:12)
at example.StackTrace.main(StackTrace.java:75)
Caused by: java.io.IOException: No space memory
at example.StackTrace$AAA.fff(StackTrace.java:51)
... 3 more
---Finish printing trace
ExceptionなくStack trace出力
上記のコードは、Exceptionが発生する場合にのみ使用することができます。
ただ、デバッグの目的でTraceを出力したい場合は以下のようにThrowableオブジェクトを作成し、 printStackTrace()
を呼び出します。
throw
するものではないため、ログのみが出力されて、オブジェクトが消滅します。
// print stack trace
(new Throwable()).printStackTrace();
結果
java.lang.Throwable
at example.StackTrace$AAA.eee(StackTrace.java:39)
at example.StackTrace$AAA.bbb(StackTrace.java:16)
at example.StackTrace$AAA.aaa(StackTrace.java:10)
at example.StackTrace.main(StackTrace.java:47)
Traceを出力せずにStringとしてインポート
Traceログに出力せずにStringオブジェクトとして取得することができます。
以下のように getStackTrace()
を呼び出すと、 StackTraceElement
配列を返します。
StackTraceElementオブジェクトは、Traceの情報を持っており、Stackが多く蓄積されるほど、配列の長さも長くなります。
このオブジェクトのアイテムをStringに出力することができます。
// get stack trace and print
StackTraceElement[] stacks = (new Throwable()).getStackTrace();
for (StackTraceElement element : stacks) {
System.out.println(element);
}
結果
example.StackTrace$AAA.ddd(StackTrace.java:31)
example.StackTrace$AAA.bbb(StackTrace.java:15)
example.StackTrace$AAA.aaa(StackTrace.java:10)
example.StackTrace.main(StackTrace.java:47)
例
次のコードは、上記の例で使用したコードです。
package example;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
public class StackTrace {
static class AAA {
void aaa() {
bbb();
}
void bbb() {
ccc();
sleep(1000);
ddd();
sleep(1000);
eee();
sleep(1000);
fff();
}
void ccc() {
try {
Exception e = new Exception();
e.initCause(new IOException("No space memory"));
throw e;
} catch(Exception e) {
e.printStackTrace();
}
}
void ddd() {
// get stack trace and print
StackTraceElement[] stacks = (new Throwable()).getStackTrace();
for (StackTraceElement element : stacks) {
System.out.println(element);
}
}
void eee() {
// print stack trace
(new Throwable()).printStackTrace();
}
void fff() {
try {
Exception e = new Exception();
e.initCause(new IOException("No space memory"));
throw e;
} catch(Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.append("+++Start printing trace:\n");
e.printStackTrace(pw);
pw.append("---Finish printing trace");
System.out.println(sw.toString());
}
}
void sleep(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) {
AAA a = new AAA();
a.aaa();
}
}
参考
Related Posts
- Java - AtomicReference使用方法
- Java - CountDownLatchを使用する方法、および例
- Java - ScheduledThreadPoolExecutor使用方法
- Java - SummaryStatisticsの使用方法(count、min、max、average)
- Java8 - 関数型インタフェース (Functional Interface) について
- Java - String配列をint配列に変換する
- Java - ArrayList要素の値を変更する方法、replaceAll()
- Java - 2つのリストが同じかどうかを比較
- Java - 配列から特定のIndex要素を削除する3つの方法
- Java - HashMapソート、4つの方法
- Java - 文字列を配列に変換する方法
- Java - ArrayListが空であることを確認する3つの方法
- Java - ArrayListの巡回、4つの方法
- Java - ArrayListの最大値、最小 値を見つける
- Java - ArrayListの合計、平均値の計算
- Java - HashMap巡回、3つの方法
- Java - do whileとwhileの違い
- Java - Lambda式と関数型インタフェース
- Java - List empty(null)チェック、3つの方法
- Java - ArrayListの初期化、4つの方法
- Java - Stream.reduce()の使い方と例
- Java - 2つのマップを結合する(merge、putAll)
- Java - java.util.Dateをjava.sql.Dateに変換する
- Java - ArrayListをStringに変換する
- Java - ClassNotFoundExceptionの発生原因と解決策
- Java - 非静的メソッドは静的コンテキストから参照できません
- Java - NoSuchMethodErrorの原因と解決策
- Java - JSONライブラリを使用する方法(JSONObject、JSONArray)
- Java - byte[]配列をFileに保存
- Java - byte[]の配列をStringに変換
- Java - ファイルのアクセス権を確認し、変更
- Java - 一時フォルダ(Temp directory)パスを取得する
- Javaでシェルスクリプトを実行
- Java - Streamを配列に変換する
- Java - リスト重複排除、2つの方法