关于调试:有没有办法转储堆栈跟踪而不在java中抛出异常?

Is there a way to dump a stack trace without throwing an exception in java?

我正在考虑为我的Java应用程序创建一个调试工具。

我想知道是否可以得到一个堆栈跟踪,就像Exception.printStackTrace(),但实际上不抛出异常?

我的目标是,在任何给定的方法中,转储一个堆栈以查看方法调用方是谁。


是的,简单地使用

1
Thread.dumpStack()


您还可以尝试使用Thread.getAllStackTraces()来获取所有活动线程的堆栈跟踪映射。???????


如果您只希望跟踪当前线程(而不是系统中的所有线程,正如RAM的建议所做的那样),请执行以下操作:

thread.currentThread().getStackTrace())

要查找呼叫者,请执行以下操作:

1
2
3
4
private String getCallingMethodName() {
    StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
    return callingFrame.getMethodName();
}

并从需要知道其调用方是谁的方法中调用该方法。但是,警告一句:列表中调用帧的索引可能会根据JVM而变化!这完全取决于在到达跟踪生成点之前GetStackTrace中有多少层调用。一个更健壮的解决方案是获取跟踪,并在跟踪上迭代,寻找getcallingmethodname的帧,然后进一步执行两个步骤来找到真正的调用者。


您可以得到这样的堆栈跟踪:

1
2
Throwable t = new Throwable();
t.printStackTrace();

如果要访问帧,可以使用t.getStackTrace()获取堆栈帧数组。

请注意,如果热点编译器一直忙于优化,则此stacktrace(与其他任何堆栈跟踪一样)可能会丢失一些帧。


注意thread.dumpstack()实际上抛出了一个异常:

1
new Exception("Stack trace").printStackTrace();


您还可以通过向进程发送一个退出信号来向JVM发送一个信号来在运行的Java进程上执行Tr.GoAltStAccTraceSe()。

在UNIX/Linux上使用:

EDCOX1为1,其中PrimeStID是Java程序的进程号。

在Windows上,您可以在应用程序中按ctrl-break,但除非运行控制台进程,否则通常不会看到这一点。

JDK6引入了另一个选项jstack命令,它将显示计算机上任何运行JDK6进程的堆栈:

jstack [-l]

这些选项对于在生产环境中运行且不易修改的应用程序非常有用。它们对于诊断运行时死锁或性能问题特别有用。

http://java.sun.com/developer/technicalArticles/programming/stacktrace/http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html


如果需要捕获输出

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

Java 9引入了EDCOX1×3和支持用于堆栈的类。

下面是来自javadoc的一些片段:

The walk method opens a sequential stream of StackFrames for the current thread and then applies the given function to walk the StackFrame stream. The stream reports stack frame elements in order, from the top most frame that represents the execution point at which the stack was generated to the bottom most frame. The StackFrame stream is closed when the walk method returns. If an attempt is made to reuse the closed stream, IllegalStateException will be thrown.

...

  • To snapshot the top 10 stack frames of the current thread,

    1
    2
    List<StackFrame> stack = StackWalker.getInstance().walk(s ->
     s.limit(10).collect(Collectors.toList()));

  • Java剖析器

    在代码中甚至不需要这样做。您可以将Java HPROF附加到您的进程和任何点命中控件上,以输出堆转储、运行线程等。…不会弄乱你的应用程序代码。这有点过时了,Java 6附带了GUI J控制台,但我仍然发现HPROF非常有用。