Javaで現在のスタックトレースを取得するにはどうすればよいですか?


1002

現在のスタックトレースを取得する方法.NETでできるように、JavaでばよいですEnvironment.StackTraceか?

見つけましたThread.dumpStack()が、それは私が欲しいものではありません-スタックトレースを取り戻したいのですが、出力しません。


73
Eclipseでデバッグしているときは、常に「new Exception()。printStackTrace()」をウォッチ式として使用しています。これは、ブレークポイントで一時停止し、どこから来たのかを知りたい場合に便利です。
TimBüthe、2009

22
@TimBüthe:デバッグモードのとき、Eclipseはすでにスタックトレースを通知していませんか?私はそう思う。
Luigi Massa Gallerano 2013

41
Arrays.toString(Thread.currentThread()。getStackTrace()); 十分に単純です。
アジェイ2013年

2
@Arkanonこれはjavaを参照し、.netでそれを行う方法とJavaで同等のものを示しています。
Pokechu22 2014年

9
うまく表示するには、Apache StringUtilsを使用できます。StringUtils.join(currentThread()。getStackTrace()、 "\ n");
アート

回答:


1159

使用できますThread.currentThread().getStackTrace()

これは、StackTraceElementプログラムの現在のスタックトレースを表すの配列を返します。


48
既にApache Commonsを使用して文字列を取得している場合は、クールなワンライナー:String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e); stackoverflow.com/a/10620951/11236
ripper234 '26

5
配列の最初の要素(インデックス0)はjava.lang.Thread.getStackTraceメソッドで、2番目の要素(インデックス1)は通常、最初の要素です。
lilalinux 14

175
例外がなく、Apache Arrays.toString(Thread.currentThread()。getStackTrace())を使用していないときに機能するスタックトレースを文字列に変換する1つのライナー
Tony

9
@Tonyのソリューションは、スロー可能オブジェクトを必要としないため、より優れています
mvd

3
以下の多くの回答で指摘されているように、子クラス()を介して呼び出すJVMの潜在的なオーバーヘッドnew Throwable().getStackTrace()をチェックthis != Thread.currentThread()してバイパスする必要がないため、処理がはるかに高速ですException extends Throwable
Vlad

264
Thread.currentThread().getStackTrace();

スタックの最初の要素が何であるかを気にしない場合は問題ありません。

new Throwable().getStackTrace();

必要に応じて、現在のメソッドの位置が定義されます。


35
(new Throwable()).getStackTrace()実行も高速です(bugs.sun.com/bugdatabase/view_bug.do?bug_id=6375302を参照)
MightyE

2
Thread.currentThread()。getStackTrace()の結果がnew Throwable()。getStackTrace()とどのように異なるかを詳しく説明できますか?両方を試したところ、Thread.currentThread()。getStackTrace()がThread.getStackTraceのインデックス0の配列を返し、呼び出し元のメソッドはインデックス1にあることがわかりました。新しいThrowable()。getStackTrace()メソッドは呼び出し元の配列を返しますインデックス0のメソッド。両方のメソッドに現在のメソッドの位置が定義されているようですが、位置が異なります。あなたが指摘している別の違いはありますか?
ライアン

9
@ Ryan、Thread.currentThread()。getStackTrace()がメソッドの異なるバージョンでその位置を維持することを約束しないという保証はありません。だから、たまたまチェックしたのはインデックス1だった。Sunの一部のバージョンのJVM(1.5または1.6、覚えていない)では、インデックス2だった。それはそこにあり、将来そこにとどまります。
Yishai 2013年

5
@MightyEバグはJava 6で修正済みとしてクローズされたと報告されました。内部を見ると(new Exception()).getStackTrace()、要求されたスタックトレースが現在のスレッド上にある場合に実行されているように見えます(常にThread.currentThread().getStackTrace();
M

3
@MJustin:バグは修正されたとして「今」報告されていません。MightyEがコメントを書き込む前に6年も修正されています。実際、Stackoverflowが設立される前でも修正されていました…
Holger

181
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
    System.out.println(ste);
}

20
javaには、Throwableで定義されたprintStackTraceメソッドがあります。new Exception().printStackTrace(System.out)これを行うことができます。これは覚えています。for ループのオーバーヘッドはおそらく少ないですが、とにかくこれをデバッグ用としてのみ使用する必要があります...
Jaap

2
最高のこのような私、あなたのprintln文をラップすることにより、ノイズ取り除く機会、例えばを得るためにfor (StackTraceElement ste : Thread.currentThread().getStackTrace()) { if(ste.toString().contains("mypackages")){ System.out.println(ste); } }
nby

61
Thread.currentThread().getStackTrace();

JDK1.5以降で使用できます。

古いバージョンでは、あなたはリダイレクトすることができますexception.printStackTrace()StringWriter()

StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();

3
new Throwable().getStackTrace()JDK1.4以降で利用可能…
Holger

40

これにはApacheのコモンズを使用できます。

String fullStackTrace = org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);

13
これは素晴らしい1行のソリューションです。FYI、誰もが使用するためorg.apache.commons.lang3、フルラインである:org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);
fileoffsetは

2
に移動するときにfileoffsetのコメントを繰り返すだけorg.apache.commons.lang3です。最初は見落としましたが、インポートではのlang3代わりにを使用しlang、に置き換えgetFullStackTraceていgetStackTraceます。
ggkmath 2013年

とても便利です!IDE(IntelliJ IDEAなど)を使用してデバッグする場合は、ExceptionUtils.getStackTrace(new Throwable())式を使用してスタックトレースを取得すると便利です。
セルゲイブルノフ


22

すべてのスレッドのスタックトレースを取得するには、jstackユーティリティ、JConsoleを使用するか、(Posixオペレーティングシステムで)kill -quitシグナルを送信します。

ただし、これをプログラムで実行する場合は、ThreadMXBeanを使用してみてください。

ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] infos = bean.dumpAllThreads(true, true);

for (ThreadInfo info : infos) {
  StackTraceElement[] elems = info.getStackTrace();
  // Print out elements, etc.
}

前述のように、現在のスレッドのスタックトレースだけが必要な場合は、はるかに簡単Thread.currentThread().getStackTrace()です。


2
この回答のコードスニペットは、JVMにQUITシグナル(UNIXのようなシステム)またはWindowsの<ctrl> <break>を送信したときに表示される種類のダンプをプログラムで生成するのに最も近いものです。他の回答とは異なり、スタックトレースだけでなく、モニターやシンクロナイザーも表示されます(たとえば、StackTraceElement配列を反復処理しSystem.err.println(elems[i])てそれぞれを実行した場合)。スニペットの2行目はのbean.前にありdumpAllThreadsませんが、ほとんどの人はそれを解決できると思います。
George Hawkins、

22

別の解決策(35 31文字のみ):

new Exception().printStackTrace();   
new Error().printStackTrace();

1
素晴らしいソリューション。今、私はすべてのスタックフレームをループする必要はありません
Vineel Kovvuri


17

トニーは、受け入れられた回答へのコメントとして、実際にOPの質問に答える最良の回答と思われるものを与えました:

Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );

... OPは、スタックトレースからを取得する方法を尋ねませんでしStringException。そして、私はApache Commonsの大ファンですが、上記のような単純なものがある場合、外部ライブラリを使用する論理的な理由はありません。


スレッドのリストがあり、スタックトレースを出力する必要があります。
Daneel S. Yaitskov

その場合は、必ずを使用しThread.getAllStackTraces()てくださいMap<Thread, StackTraceElement[]>。ホットスポットは、スレッドをセーフポイントする必要があるときはいつでも、すべてのスレッドをセーフポイントします。Zingは、他のスレッドに影響を与えることなく、個々のスレッドをセーフポイントに移動できます。スタックトレースを取得するには、セーフポイントが必要です。Thread.getAllStackTraces()すべてのスタックトレースを取得し、すべてのスレッドを一度だけ停止します。もちろん、あなたが実際に興味を持っていたマッピングを知る必要があります。
ラルフ・H

14

私はそれを提案します

  Thread.dumpStack()

より簡単な方法であり、まったく問題がない場合に例外やスロー可能オブジェクトを実際に作成しないという利点があり、かなり重要です。


1
さて、実際には、dumpStack()は静的メソッドであり、静的な方法でアクセスする必要があります。ありがとう、日食!
Thomas Adkins 2017

1
私はショートカットが大好きですが、このメソッドのソースコードは次のとおりです。つまり、new Exception("Stack trace").printStackTrace();実際にThrowableを構築しています
Florent

13

スタックトレースを取得する:

StackTraceElement[] ste = Thread.currentThread().getStackTrace();

スタックトレースの印刷(JAVA 8+):

Arrays.asList(ste).forEach(System.out::println);

Stacktrageの印刷(JAVA 7):

StringBuilder sb = new StringBuilder();

for (StackTraceElement st : ste) {
    sb.append(st.toString() + System.lineSeparator());
}
System.out.println(sb);

12

Java 9には新しい方法があります。

public static void showTrace() {

  List<StackFrame> frames =
    StackWalker.getInstance( Option.RETAIN_CLASS_REFERENCE )
               .walk( stream  -> stream.collect( Collectors.toList() ) );

  for ( StackFrame stackFrame : frames )
    System.out.println( stackFrame );
}

面白い。:-)
djangofan

10

スタックトレースで文字列を返すユーティリティメソッドがあります。

static String getStackTrace(Throwable t) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw, true);
    t.printStackTrace(pw);
    pw.flush();
    sw.flush();
    return sw.toString();
}

そしてちょうどロジットのように...

... 
catch (FileNotFoundException e) {
    logger.config(getStackTrace(e));
}

これは、Netbeansによって自動生成されたもののようです。
Leif Gruenwoldt

は、組み込みのロガー、または作成してファイルに書き込むロガーです。
Doug Hauf、2014

@Doug Hauf、ロガーは組み込みのJavaロガーへの参照です。logging.propertiesファイルを必ず構成してください。次のように、クラスの先頭に追加します。private static final Logger logger = Logger.getLogger(Your_Class_Name.class.getName());
サルバドールバレンシア

1
java.util.logging.Logger#log(Level, String, Throwable)すでにこれを行います。これは、Java標準ライブラリにすでに存在するものを不必要に書き直しており、ドキュメントから離れた間違った方向に新しい開発者を指しています。これにより、スタックトレースを特定の方法でフォーマットするように強制されましたlogging。APIを使用すると、ログステートメントのフォーマットを指定どおりに動的に変更できます。私の知る限り、log4j同様の振る舞いもあります。私が説明したようなものを失うことになるので、車輪を再発明しないでください。
searchengine27

1
2012年にも存在しました。残念ながら、日付はあなたのケースで違いはありません。[link](docs.oracle.com/javase/1.5.0/docs/api/java/util/logging/Logger.html#log(java.util.logging.Level、java.lang.String、java.lang)を参照してください.Throwable))、[link](docs.oracle.com/javase/1.5.0/docs/api/java/util/logging/Logger.html#log(java.util.logging.LogRecord))など(あります合格いくつかの機能しているThrowableにオフHandlerに至る秒Formatter。私はここにリストされてきた以上、Java7だった2012年にSと、これらの機能が戻ってはるかに長くJava7が回避されているよりも、デート、したがって、J2SE 5.0のjavadoc)
searchengine27


8
try {
}
catch(Exception e) {
    StackTraceElement[] traceElements = e.getStackTrace();
    //...
}

または

Thread.currentThread().getStackTrace()

あなたの一番上の例は、try / catchブロックに関連するスタックトレースだけを与えるのではないですか?
Dan Monego 2009

1
2つの違いは何
ですか

5

多分あなたはこれを試すことができます:

catch(Exception e)
{
    StringWriter writer = new StringWriter();
    PrintWriter pw = new PrintWriter(writer);
    e.printStackTrace(pw);
    String errorDetail = writer.toString();
}

文字列「errorDetail」にはスタックトレースが含まれています。


5
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();

配列の最後の要素はスタックの最下部を表します。これは、シーケンス内で最も古いメソッド呼び出しです。

A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName().

StackTraceElementをループして、目的の結果を取得します。

for (StackTraceElement ste : stackTraceElements ) 
{
    //do your stuff here...
}

最後の要素に最新の要素が含まれていることに言及していただきありがとうございます。直感に反し、時間を節約できました。
クリアライト2015

また、.toString()は、すべてのデータを文字列に適切に出力します
Vlad

4

上記の回答を使用して書式を追加しました

public final class DebugUtil {

    private static final String SEPARATOR = "\n";

    private DebugUtil() {
    }

    public static String formatStackTrace(StackTraceElement[] stackTrace) {
        StringBuilder buffer = new StringBuilder();
        for (StackTraceElement element : stackTrace) {
            buffer.append(element).append(SEPARATOR);
        }
        return buffer.toString();
    }

    public static String formatCurrentStacktrace() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        return formatStackTrace(stackTrace);
    }
}

2

プロセスの現在のコールスタックを確認する場合は、jstackユーティリティを使用できます。

Usage:
    jstack [-l] <pid>
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)

Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
    -m  to print both java and native frames (mixed mode)
    -l  long listing. Prints additional information about locks
    -h or -help to print this help message

1

これは古い投稿ですが、これが私の解決策です:

Thread.currentThread().dumpStack();

そこでのより多くの情報とメソッド:http : //javarevisited.blogspot.fr/2013/04/how-to-get-current-stack-trace-in-java-thread.html


3
Thread.dumpStack()は静的なので、直接呼び出す必要があります。
David Avendasora 2016年

2
OPは、スタックトレースを出力するのではなく、コードで参照することを望んでいることを示しました。
テイラーR

1
@DavidAvendasoraが述べたようにThread.dumpStack()、静的メソッドなので直接呼び出す必要があります。
M-WaJeEh 2017年

はい、java.lang.Thread.dumpStack()はJava 11で動作します
Park JongBum

-3

System.out.println(Arrays.toString(Thread.currentThread().getStackTrace()));

これは、ループなしでスタックトレースを出力するのに役立ちます。


1
あなたの答えは、私が3か月前に投稿したものと同じです。
マイクげっ歯類'10
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.