有没有办法在java中转储堆栈跟踪而不引发异常?

发布于 2024-07-23 06:23:33 字数 148 浏览 10 评论 0 原文

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

我想知道是否有可能获得堆栈跟踪,就像 Exception.printStackTrace() 一样,但实际上不会引发异常?

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

I am thinking of creating a debug tool for my Java application.

I am wondering if it is possible to get a stack trace, just like Exception.printStackTrace() but without actually throwing an exception?

My goal is to, in any given method, dump a stack to see who the method caller is.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

栀子花开つ 2024-07-30 06:23:33

是的,只需使用

Thread.dumpStack()

Yes, simply use

Thread.dumpStack()
铁轨上的流浪者 2024-07-30 06:23:33

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

You can also try Thread.getAllStackTraces() to get a map of stack traces for all the threads that are alive.​​​​​​

栀梦 2024-07-30 06:23:33

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

Thread.currentThread().getStackTrace()

要查找调用者,请执行以下操作:

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

并从需要的方法中调用该方法知道它的调用者是谁。 但是,请注意:列表中调用框架的索引可能会根据 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:

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.

千仐 2024-07-30 06:23:33

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

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

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

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

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.

Be aware that this stacktrace (just like any other) may be missing some frames if the hotspot compiler has been busy optimizing things.

随波逐流 2024-07-30 06:23:33

请注意,Thread.dumpStack() 实际上创建了一个异常:

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

Notice that Thread.dumpStack() actually creates an exception:

new Exception("Stack trace").printStackTrace();
瑕疵 2024-07-30 06:23:33

Java 9 引入了 StackWalker< /a> 以及用于遍历堆栈的支持类。

以下是 Javadoc 中的一些片段:

walk 方法打开 StackFrames 用于当前线程,然后应用给定函数来遍历 StackFrame 流。 该流按顺序报告堆栈帧元素,从表示生成堆栈的执行点的最顶部帧到最底部帧。 当 walk 方法返回时,StackFrame 流将关闭。 如果尝试重用已关闭的流,将抛出 IllegalStateException

...

  • 要快照当前线程的前 10 个堆栈帧,

    List;   堆栈 = StackWalker.getInstance().walk(s -> 
       s.limit(10).collect(Collectors.toList())); 
      
  • Java 9 introduced the StackWalker and supporting classes for walking the stack.

    Here are a few snippets from the 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.

    ...

    1. To snapshot the top 10 stack frames of the current thread,

      List<StackFrame> stack = StackWalker.getInstance().walk(s ->
       s.limit(10).collect(Collectors.toList()));
      
    佞臣 2024-07-30 06:23:33

    如果您乐意输出到 stderrRob Di Marco 的回答 是迄今为止最好的。

    如果您想捕获到一个String,并按照正常跟踪换行,您可以这样做:

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

    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:

    Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );
    
    笑看君怀她人 2024-07-30 06:23:33

    如果您需要捕获输出

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

    If you need capture output

    StringWriter sw = new StringWriter();
    new Throwable("").printStackTrace(new PrintWriter(sw));
    String stackTrace = sw.toString();
    
    柒夜笙歌凉 2024-07-30 06:23:33

    您还可以通过向正在运行的 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

    陌上青苔 2024-07-30 06:23:33

    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.

    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文