有没有办法在java中转储堆栈跟踪而不引发异常?
我正在考虑为我的 Java 应用程序创建一个调试工具。
我想知道是否有可能获得堆栈跟踪,就像 Exception.printStackTrace() 一样,但实际上不会引发异常?
我的目标是,在任何给定的方法中,转储堆栈以查看方法调用者是谁。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
是的,只需使用
Yes, simply use
您还可以尝试 Thread.getAllStackTraces() 来获取所有活动线程的堆栈跟踪映射。
You can also try
Thread.getAllStackTraces()
to get a map of stack traces for all the threads that are alive.如果您只想跟踪当前线程(而不是像 Ram 的建议那样跟踪系统中的所有线程),请执行以下操作:
Thread.currentThread().getStackTrace()
要查找调用者,请执行以下操作:
并从需要的方法中调用该方法知道它的调用者是谁。 但是,请注意:列表中调用框架的索引可能会根据 JVM 的不同而有所不同! 这完全取决于在到达生成跟踪的点之前 getStackTrace 中有多少层调用。 更可靠的解决方案是获取跟踪,并迭代它以查找 getCallingMethodName 的框架,然后进一步向上两步找到真正的调用者。
If you want the trace for just the current thread (rather than all the threads in the system, as Ram's suggestion does), do:
Thread.currentThread().getStackTrace()
To find the caller, do:
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.
您可以获得这样的堆栈跟踪:
如果您想访问该帧,您可以使用 t.getStackTrace() 来获取堆栈帧数组。
请注意,如果热点编译器一直忙于优化事物,则此堆栈跟踪(就像任何其他堆栈跟踪一样)可能会丢失一些帧。
You can get a stack trace like this:
If you want to access the frame, you can use
t.getStackTrace()
to get an array of stack frames.Be aware that this stacktrace (just like any other) may be missing some frames if the hotspot compiler has been busy optimizing things.
请注意,Thread.dumpStack() 实际上创建了一个异常:
Notice that Thread.dumpStack() actually creates an exception:
Java 9 引入了
StackWalker
< /a> 以及用于遍历堆栈的支持类。以下是 Javadoc 中的一些片段:
Java 9 introduced the
StackWalker
and supporting classes for walking the stack.Here are a few snippets from the Javadoc:
如果您乐意输出到
stderr
,Rob Di Marco 的回答 是迄今为止最好的。如果您想捕获到一个
String
,并按照正常跟踪换行,您可以这样做:The answer by Rob Di Marco is by far the best if you are happy to output to
stderr
.If you want to capture to a
String
, with new lines as per a normal trace, you could do this:如果您需要捕获输出
If you need capture output
您还可以通过向正在运行的 Java 进程发送 QUIT 信号来向 JVM 发送信号以执行 Thread.getAllStackTraces()。
在 Unix/Linux 上使用:
kill -QUIT process_id
,其中 process_id 是 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
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.
On Unix/Linux use:
kill -QUIT process_id
, where process_id is the process number of your Java program.On Windows, you can press Ctrl-Break in the application, although you usually won't see this unless you're running a console process.
JDK6 introduced another option, the jstack command, which will display the stack from any running JDK6 process on your computer:
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
HPROF Java Profiler
你甚至不知道必须在代码中执行此操作。 您可以将 Java HPROF 附加到您的进程,并在任何时候点击 Control-\ 来输出堆转储、运行线程等。 。 。 不会弄乱您的应用程序代码。 这有点过时了,Java 6 附带了 GUI jconsole,但我仍然发现 HPROF 非常有用。
HPROF Java Profiler
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.