在Java中获取当前堆栈跟踪

rip*_*234 966 java stack-trace

如何在Java中获取当前堆栈跟踪,就像在.NET中一样Environment.StackTrace

顺便说一句,Thread.dumpStack()不是我想要的 - 我想让堆栈追溯,而不是打印出来.

jjn*_*guy 1128

你可以用Thread.currentThread().getStackTrace().

返回一个StackTraceElements 数组,表示程序的当前堆栈跟踪.

  • 一个一个班轮堆栈跟踪转换当你没有一个例外,你不使用Apache Arrays.toString一个可行的字符串(Thread.currentThread().的getStackTrace()) (159认同)
  • 如果你已经使用apache commons来获取字符串,那就是一个很酷的单行:`String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e);`http://stackoverflow.com/a/一万一千二百三十六分之一千○六十二万○九百五十一 (46认同)
  • @Tony的解决方案更好,因为它不需要抛出 (9认同)
  • 数组中的第一个元素(索引0)是java.lang.Thread.getStackTrace方法,第二个(索引1)通常是第一个感兴趣的方法. (4认同)
  • 正如下面的许多答案所指出的那样 - 新的Throwable().getStackTrace()`要快得多,因为它不需要检查`this!= Thread.currentThread()`并绕过通过子进程调用它的潜在JVM开销-class(`Exception extends Throwable`) (3认同)

Yis*_*hai 257

Thread.currentThread().getStackTrace();
Run Code Online (Sandbox Code Playgroud)

如果您不关心堆栈的第一个元素是什么,那就没问题.

new Throwable().getStackTrace();
Run Code Online (Sandbox Code Playgroud)

如果这很重要,将为您当前的方法定义一个位置.

  • `(new Throwable()).getStackTrace()`执行速度更快(参见http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6375302) (34认同)
  • @Ryan,无法保证Thread.currentThread().getStackTrace()不保证在该方法的不同版本上保持该位置.因此当你碰巧检查它是在索引1时.对于Sun的某个版本的JVM(1.5或1.6,不记得),它是索引2.这就是我所说的定义位置 - 规范要求它会在那里,并在未来留在那里. (9认同)
  • @MightyE现在报告该错误在Java 6中被修复为封闭.看看内部,当请求的堆栈跟踪在当前线程上时,它看起来像`(new Exception()).getStackTrace()` `Thread.currentThread().getStackTrace();`总是如此 (5认同)
  • @MJustin:这个错误不是"现在"报道固定的,它在MightyE写评论之前已经修复了六年.事实上,它甚至在Stackoverflow成立之前就已得到修复...... (3认同)
  • 你能否更详细地解释一下Thread.currentThread().getStackTrace()的结果可能与新的Throwable().getStackTrace()不同?我试过两个,发现Thread.currentThread().getStackTrace()在索引0中返回带有Thread.getStackTrace的am数组,调用方法在索引1处.新的Throwable().getStackTrace()方法返回一个带调用的数组索引为0的方法.似乎两种方法都有当前方法的定义位置,但位置不同.你指出还有另外一个区别吗? (2认同)

Lei*_*ldt 178

for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
    System.out.println(ste);
}
Run Code Online (Sandbox Code Playgroud)

  • java有一个在Throwable上定义的printStackTrace方法,你可以这样做:`new Exception().printStackTrace(System.out)`我记得,for循环可能有较少的开销,但你应该只使用它作为调试的东西... (17认同)
  • 我最喜欢这一点,因为您可以通过包装println语句来消除噪音,例如`for(StackTraceElement ste:Thread.currentThread()。getStackTrace()){if(ste.toString()。contains(“ mypackages“)){System.out.println(ste); }}` (2认同)

Rea*_*wTo 61

Thread.currentThread().getStackTrace();
Run Code Online (Sandbox Code Playgroud)

自JDK1.5起可用.

对于旧版本,您可以重定向exception.printStackTrace()StringWriter():

StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
Run Code Online (Sandbox Code Playgroud)

  • `new Throwable().getStackTrace()` 从 JDK1.4 开始可用...... (3认同)

sti*_*kos 39

你可以使用Apache的公共资源:

String fullStackTrace = org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的单线解决方案.仅供参考,对于使用`org.apache.commons.lang3`的人来说,整行是:`org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);` (13认同)
  • 只是在转移到我最初忽略的`org.apache.commons.lang3`时重申fileoffset的注释 - 导入使用`lang3`而不是`lang`,并用`getStackTrace`替换`getFullStackTrace`. (2认同)

Vic*_*dia 24

在android上更简单的方法是使用这个:

import android.util.Log;
String stackTrace = Log.getStackTraceString(exception); 
Run Code Online (Sandbox Code Playgroud)

  • android.util.Log.getStackTraceString http://developer.android.com/reference/android/util/Log.html (6认同)
  • getStackTraceString在哪里定义?这来自第三方日志库吗? (4认同)

kuk*_*kis 22

另一个解决方案(只有35个 31个字符):

new Exception().printStackTrace();   
new Error().printStackTrace();
Run Code Online (Sandbox Code Playgroud)


Ada*_*ski 20

要获得所有线程的堆栈跟踪,您可以使用jstack实用程序,JConsole或发送kill -quit信号(在Posix操作系统上).

但是,如果要以编程方式执行此操作,可以尝试使用ThreadMXBean:

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

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

如上所述,如果你只想要当前线程的堆栈跟踪,那就容易多了 - 只需使用Thread.currentThread().getStackTrace();

  • 这个答案中的代码片段最接近于以编程方式生成您在向JVM发送QUIT信号(在类似Unix的系统上)或Windows上的<ctrl> <break>时看到的转储类型.与其他答案不同,您可以看到监视器和同步器以及堆栈跟踪(例如,如果迭代StackTraceElement数组并在每个上执行`System.err.println(elems [i])`.代码片段中的第二行在`dumpAllThreads`之前缺少`bean`但我想大多数人都可以解决这个问题. (2认同)

mik*_*ent 17

托尼作为对已接受答案的评论,给出了实际回答OP问题的最佳答案:

Arrays.toString(Thread.currentThread().getStackTrace());
Run Code Online (Sandbox Code Playgroud)

...的OP也不要问如何获得String从一个堆栈跟踪Exception.虽然我是Apache Commons的忠实粉丝,但是当有一些像上面那样简单的东西时,没有合理的理由使用外部库.


rip*_*234 16

傻我,是的 Thread.currentThread().getStackTrace();


Tho*_*ins 14

我建议

  Thread.dumpStack()
Run Code Online (Sandbox Code Playgroud)

这是一种更简单的方法,并且具有在没有任何问题的情况下实际上不构建异常或抛出的优点,并且更加重要.

  • 我喜欢这个快捷方式,但是这个方法的源代码是:`new Exception("Stack trace").printStackTrace();` 所以它实际上是在构建一个 Throwable (3认同)

Chr*_*oom 11

在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 );
}
Run Code Online (Sandbox Code Playgroud)


Sal*_*cia 10

我有一个实用程序方法,返回带有stacktrace的字符串:

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();
}
Run Code Online (Sandbox Code Playgroud)

只是像logit一样...

... 
catch (FileNotFoundException e) {
    logger.config(getStackTrace(e));
}
Run Code Online (Sandbox Code Playgroud)


Zit*_*rax 10

要用番石榴串:

Throwables.getStackTraceAsString(new Throwable())
Run Code Online (Sandbox Code Playgroud)


but*_*ken 8

try {
}
catch(Exception e) {
    StackTraceElement[] traceElements = e.getStackTrace();
    //...
}
Run Code Online (Sandbox Code Playgroud)

要么

Thread.currentThread().getStackTrace()
Run Code Online (Sandbox Code Playgroud)

  • 两者有什么区别 (2认同)

Wit*_*rba 7

获取堆栈跟踪:

StackTraceElement[] ste = Thread.currentThread().getStackTrace();
Run Code Online (Sandbox Code Playgroud)

打印堆栈跟踪(JAVA 8+):

Arrays.asList(ste).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

打印堆叠(JAVA 7):

StringBuilder sb = new StringBuilder();

for (StackTraceElement st : ste) {
    sb.append(st.toString() + System.lineSeparator());
}
System.out.println(sb);
Run Code Online (Sandbox Code Playgroud)


小智 5

也许您可以尝试以下方法:

catch(Exception e)
{
    StringWriter writer = new StringWriter();
    PrintWriter pw = new PrintWriter(writer);
    e.printStackTrace(pw);
    String errorDetail = writer.toString();
}
Run Code Online (Sandbox Code Playgroud)

字符串“ errorDetail”包含堆栈跟踪。


Xar*_*mer 5

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
Run Code Online (Sandbox Code Playgroud)

数组的最后一个元素表示堆栈的底部,这是序列中最近的方法调用。

A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName().
Run Code Online (Sandbox Code Playgroud)

遍历StackTraceElement并获得所需的结果。

for (StackTraceElement ste : stackTraceElements ) 
{
    //do your stuff here...
}
Run Code Online (Sandbox Code Playgroud)


Sam*_*ath 5

如果您想检查进程的当前调用堆栈,可以使用 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
Run Code Online (Sandbox Code Playgroud)