有没有办法转储堆栈跟踪而不在java中抛出异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/944991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way to dump a stack trace without throwing an exception in java?
提问by corgrath
I am thinking of creating a debug tool for my Java application.
我正在考虑为我的 Java 应用程序创建一个调试工具。
I am wondering if it is possible to get a stack trace, just like Exception.printStackTrace()
but without actually throwing an exception?
我想知道是否有可能获得堆栈跟踪,就像Exception.printStackTrace()
但实际上不抛出异常一样?
My goal is to, in any given method, dump a stack to see who the method caller is.
我的目标是,在任何给定的方法中,转储堆栈以查看方法调用者是谁。
采纳答案by Prabhu R
You can also try Thread.getAllStackTraces()
to get a map of stack traces for all the threads that are alive.??????
您还可以尝试Thread.getAllStackTraces()
获取所有活动线程的堆栈跟踪图。??????
回答by Rob Di Marco
Yes, simply use
是的,只需使用
Thread.dumpStack()
回答by Gerco Dries
You can get a stack trace like this:
您可以获得这样的堆栈跟踪:
Throwable t = new Throwable();
t.printStackTrace();
If you want to access the frame, you can use t.getStackTrace() to get an array of stack frames.
如果要访问帧,可以使用 t.getStackTrace() 获取堆栈帧数组。
Be aware that this stacktrace (just like any other) may be missing some frames if the hotspot compiler has been busy optimizing things.
请注意,如果热点编译器一直忙于优化事物,则此堆栈跟踪(与任何其他跟踪一样)可能会丢失一些帧。
回答by Tom Anderson
If you want the trace for just the current thread (rather than all the threads in the system, as Ram's suggestion does), do:
如果您只想跟踪当前线程(而不是系统中的所有线程,正如 Ram 的建议所做的那样),请执行以下操作:
Thread.currentThread().getStackTrace()
Thread.currentThread()。getStackTrace()
To find the caller, do:
要找到来电者,请执行以下操作:
private String getCallingMethodName() {
StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
return callingFrame.getMethodName();
}
And call that method from within the method that needs to know who its caller is. However, a word of warning: the index of the calling frame within the list could vary according to the JVM! It all depends on how many layers of calls there are within getStackTrace before you hit the point where the trace is generated. A more robust solution would be to get the trace, and iterate over it looking for the frame for getCallingMethodName, then take two steps further up to find the true caller.
并从需要知道其调用者是谁的方法中调用该方法。但是,警告一句:列表中调用帧的索引可能会因 JVM 的不同而有所不同!这完全取决于在到达生成跟踪点之前 getStackTrace 中有多少层调用。更健壮的解决方案是获取跟踪,并对其进行迭代以查找 getCallingMethodName 的框架,然后再采取两个步骤以找到真正的调用者。
回答by Gandalf
You don't even have to do this in the code. You can attach the Java HPROF to your process and at any point hit Control-\ to output heap dump, running threads, etc . . . without mucking up your application code. This is a bit outdated, Java 6 comes with the GUI jconsole, but I still find HPROF to be very useful.
您甚至不必在代码中执行此操作。您可以将 Java HPROF 附加到您的进程,并随时点击 Control-\ 以输出堆转储、正在运行的线程等。. . 无需弄乱您的应用程序代码。这有点过时了,Java 6 带有 GUI jconsole,但我仍然发现 HPROF 非常有用。
回答by Andrew Newdigate
You can also send a signal to the JVM to execute Thread.getAllStackTraces() on a running Java process by sending a QUIT signal to the process.
您还可以通过向正在运行的 Java 进程发送 QUIT 信号,向 JVM 发送信号以在该进程上执行 Thread.getAllStackTraces()。
On Unix/Linux use:
在 Unix/Linux 上使用:
kill -QUIT process_id
, where process_id is the process number of your Java program.
kill -QUIT process_id
,其中 process_id 是 Java 程序的进程号。
On Windows, you can press Ctrl-Break in the application, although you usually won't see this unless you're running a console process.
在 Windows 上,您可以在应用程序中按 Ctrl-Break,尽管您通常不会看到这一点,除非您正在运行控制台进程。
JDK6 introduced another option, the jstack command, which will display the stack from any running JDK6 process on your computer:
JDK6 引入了另一个选项,即 jstack 命令,它将显示您计算机上任何正在运行的 JDK6 进程的堆栈:
jstack [-l] <pid>
jstack [-l] <pid>
These options are very useful for applications which are running in a production environment and cannot be modified easily. They're especially useful for diagnosing runtime deadlocks or performance problems.
这些选项对于在生产环境中运行且无法轻松修改的应用程序非常有用。它们对于诊断运行时死锁或性能问题特别有用。
http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html
http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/ http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html
回答by Ariel T
Notice that Thread.dumpStack() actually throws an exception:
注意 Thread.dumpStack() 实际上抛出了一个异常:
new Exception("Stack trace").printStackTrace();
回答by Ricardo Jl Rufino
If you need capture output
如果您需要捕获输出
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
回答by mkobit
Java 9 introduced the StackWalker
and supporting classes for walking the stack.
Java 9 引入了StackWalker
用于遍历堆栈的类和支持类。
Here are a few snippets from the Javadoc:
以下是 Javadoc 中的一些片段:
The
walk
method opens a sequential stream ofStackFrames
for the current thread and then applies the given function to walk theStackFrame
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. TheStackFrame
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,
List<StackFrame> stack = StackWalker.getInstance().walk(s -> s.limit(10).collect(Collectors.toList()));
该
walk
方法StackFrames
为当前线程打开一个顺序流,然后应用给定的函数来遍历StackFrame
流。流按顺序报告堆栈帧元素,从代表生成堆栈的执行点的最顶部帧到最底部帧。该StackFrame
流已关闭的步行方法返回时。如果尝试重用关闭的流,IllegalStateException
将抛出。...
要对当前线程的前 10 个堆栈帧进行快照,
List<StackFrame> stack = StackWalker.getInstance().walk(s -> s.limit(10).collect(Collectors.toList()));
回答by mike rodent
The answer by Rob Di Marcois by far the best if you are happy to output to stderr
.
该罗布迪马可的答案是迄今为止最好的,如果你很高兴地输出stderr
。
If you want to capture to a String
, with new lines as per a normal trace, you could do this:
如果您想String
按照正常跟踪使用新行捕获到 a ,您可以执行以下操作:
Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );