CLOVER🍀

That was when it all began.

Threadのスタックトレース系のメソッド

たまに簡易的にデバッグする時に

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)

自分、けっこう基礎的なことを知らないのではないでしょうか…。