たまに簡易的にデバッグする時に
new Exception().printStackTrace();
的なことを書くことがあるのですが、Threadクラスで似たようなことができるのを最近知りました。
というか、最近知りましたネタ多いですね、このところ。
Thread#dumpStack、Thread#getStackTrace、Thread.getAllStackTracesというメソッドについて。
dumpStackは、現在のスレッドのスタックトレースを出力してくれます。
Thread.dumpStack();
みんな大好きe.printStackTraceと変わらないですね。ただ、Threadクラス自体のスタックトレースが含まれてしまいますが。
getStackTraceは、現在のスレッドのStackTraceElementを配列で取得できます。
StackTraceElement[] elms = Thread.currentThread().getStackTrace(); // 0番目は、Threadのものとなる for (int i = 0; i < elms.length; i++) { System.out.printf("%s: %s%n", "getStackTrace", elms[i]); }
最初の要素は、Threadクラスのものが入ります。
getAllStackTracesは、全スレッドのスタックトレースが得られます。
java.util.Map<Thread, StackTraceElement[]> threads = Thread.getAllStackTraces(); for (java.util.Map.Entry<Thread, StackTraceElement[]> entry : threads.entrySet()) { for (int i = 0; i < entry.getValue().length; i++) { System.out.printf("[%s] %s%n", entry.getKey().getName(), entry.getValue()[i]); } }
これもやっぱり、自スレッドのものはThreadクラスのものが混じります。
試してみましょう。
ThreadStackTrace.java
public class ThreadStackTrace { public static void main(String... args) { dumpStackTrace(); printStackTrace(); printAllStackTraces(); } private static void dumpStackTrace() { Thread.dumpStack(); } private static void printStackTrace() { StackTraceElement[] elms = Thread.currentThread().getStackTrace(); // 0番目は、Threadのものとなる for (int i = 0; i < elms.length; i++) { System.out.printf("%s: %s%n", "getStackTrace", elms[i]); } } private static void printAllStackTraces() { java.util.Map<Thread, StackTraceElement[]> threads = Thread.getAllStackTraces(); for (java.util.Map.Entry<Thread, StackTraceElement[]> entry : threads.entrySet()) { for (int i = 0; i < entry.getValue().length; i++) { System.out.printf("[%s] %s%n", entry.getKey().getName(), entry.getValue()[i]); } } } }
結果。
dumpStack。
java.lang.Exception: Stack trace at java.lang.Thread.dumpStack(Thread.java:1364) at ThreadStackTrace.dumpStackTrace(ThreadStackTrace.java:9) at ThreadStackTrace.main(ThreadStackTrace.java:3)
getStackTrace。
getStackTrace: java.lang.Thread.getStackTrace(Thread.java:1588) getStackTrace: ThreadStackTrace.printStackTrace(ThreadStackTrace.java:13) getStackTrace: ThreadStackTrace.main(ThreadStackTrace.java:4)
getAllStackTraces。
[Finalizer] java.lang.Object.wait(Native Method) [Finalizer] java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135) [Finalizer] java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151) [Finalizer] java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189) [Reference Handler] java.lang.Object.wait(Native Method) [Reference Handler] java.lang.Object.wait(Object.java:503) [Reference Handler] java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133) [main] java.lang.Thread.dumpThreads(Native Method) [main] java.lang.Thread.getAllStackTraces(Thread.java:1639) [main] ThreadStackTrace.printAllStackTraces(ThreadStackTrace.java:22) [main] ThreadStackTrace.main(ThreadStackTrace.java:5)
自分、けっこう基礎的なことを知らないのではないでしょうか…。