首页 > 编程知识 正文

java打印线程堆栈(堆栈信息怎么看)

时间:2023-05-04 01:42:37 阅读:77251 作者:1100

部署yingyourjavacodetoproductionlimitsyourtroubleshootingoptions.connectingtoyourappinproductionwithadebuggerisusuallllyoutof andyoumightnotevenbeabletogetconsoleaccess.soevenwithmonitoring,you’regoingtoenduptroubleshootingmanyproblemspost-mortiod

是的。 如果有堆栈跟踪的记录,那就太好了。 这就像一次性给你指南针、地图、头等舱机票一样! 讨论一下什么是Java堆栈跟踪,以及如何使用它吧。

什么是Java堆栈跟踪? 堆栈跟踪也称为堆栈回溯,或简称为回溯。 堆栈帧的列表。 这些帧表示正在执行APP应用程序的时间。 堆栈帧是有关代码调用的方法或函数的信息。 因此,Java堆栈跟踪是一个从当前方法开始并扩展到程序启动时的帧列表。

堆栈和堆栈之间可能会发生混乱。 一叠纸是数据结构,就像桌子上的一叠纸。 先进先出。 将文档添加到文件堆栈中,并按与置入顺序相反的顺序删除。 更确切地说,堆栈称为运行时或调用堆栈,是程序在运行时创建的一组堆栈帧,由堆栈数据结构组织而成。

请看一个例子。

Java堆栈跟踪示例看看Java程序。 此类调用四个方法,从最后一个方法开始将堆栈跟踪打印到控制台。

公共类堆栈跟踪{一种公共静态语音主(字符串[ ] args ) }; }静态void a () (b ); }静态void b () c ); )静态void c () d ); (静态void d ) ) { Thread.dumpStack; }上课时,可以看到以下内容。

java.lang.Exception :堆栈跟踪为java.base/Java.lang.thread.dumpstack (thread.Java :1383 )是com.ericgoebelbecker.stack traces.stack trace.d )堆栈跟踪. Java:19 )位于com.ericgoebelbecker.stack traces.stack trace.b ) stacktrace.Java339 )上的trace.a (stack trace.b ) 位于tacktrace.main ) stacktrace.Java33607 ) d )中的main (方法位于程序启动的位置,因此位于底部。 程序启动后,Java运行时执行main ()方法。 Main (称为a )。 a (为b ),b ) )为c ),后者为d )。 最后,称为d (是dumpStack ) )生成输出。 此Java堆栈跟踪提供了程序执行顺序的图像。

Java堆栈跟踪是一个瞬间的快照。 你可以知道APP应用程序在哪里,以及它是如何到达那里的。 这是宝贵的见解,可以使用几种不同的方法。

如何使用Java堆栈跟踪已验证是否显示Java堆栈跟踪,如何使用?

Java异常堆栈跟踪和异常通常是相互关联的。 当您看到Java APP应用程序引发异常时,通常会看到与其一起记录的堆栈跟踪。 这是异常是如何工作的?

当Java代码抛出异常时,它将查找具有处理程序的方法,该处理程序可以在运行时在堆栈中处理该异常。 如果找到一个的话,它会把异常传达给它。 否则,程序将退出。 因此,异常和调用栈是直接链接的。 了解这种关系有助于阐明代码为什么引起异常。

更改示例代码吧。

首先,d ) )修改方法。

静态void d ()新建nullpointerexception )“oops! ”); }然后修改main (和a )以允许main捕获异常。 必须将要检查的异常添加到a (,以便代码可以编译。

公共语音主(字符串[ ] args )尝试)一种); }抓住(InvalidClassException ice ) system.err.println (ice.getmessage ) ); }静态void a ()抛出InvalidClassExcept

ion {   b(); }

您故意抓住“错误”例外。 运行此代码,然后观察会发生什么。

线程“主”中的异常java.lang.NullPointerException:糟糕! 在com.ericgoebelbecker.stacktraces.StackTrace.d(StackTrace.java:29) 在com.ericgoebelbecker.stacktraces.StackTrace.c(StackTrace.java:24) 在com.ericgoebelbecker.stacktraces.StackTrace.b(StackTrace.java:20) 在com.ericgoebelbecker.stacktraces.StackTrace.a(StackTrace.java:16) 在com.ericgoebelbecker.stacktraces.StackTrace.main(StackTrace.java:9)

异常使通过main()的堆栈冒泡,因为您试图捕获其他异常。 因此,运行时将其抛出,从而终止了应用程序。 不过,您仍然可以看到堆栈跟踪,因此很容易确定发生了什么。

现在,更改main()以捕获NullPointerException。 您也可以从a()中删除已检查的异常。

公共静态void main(String [] args){   尝试{     一种();   }抓(NullPointerException ice){     System.err.println(ice.getMessage());   } } 静态void a(){   b(); }

重新运行程序。

糟糕!

我们丢失了堆栈跟踪! 通过仅打印附加到异常的消息,您错过了一些重要的上下文。 除非你记得你为什么写糟糕!在该消息中,查找此问题将变得很复杂。 让我们再试一次。

公共静态void main(String [] args){   尝试{     一种();   } catch(NullPointerException npe){     npe.printStackTrace();   } }

重新运行该应用程序。

java.lang.NullPointerException:糟糕! 在com.ericgoebelbecker.stacktraces.StackTrace.d(StackTrace.java:28) 在com.ericgoebelbecker.stacktraces.StackTrace.c(StackTrace.java:24) 在com.ericgoebelbecker.stacktraces.StackTrace.b(StackTrace.java:20) 在com.ericgoebelbecker.stacktraces.StackTrace.a(StackTrace.java:16) 在com.ericgoebelbecker.stacktraces.StackTrace.main(StackTrace.java:9)

这样更好! 我们看到了堆栈跟踪,它在发生异常的d()处结束,即使main()打印了它。

记录Java堆栈跟踪

如果您不想将错误消息打印到控制台,而是打印到日志文件,该怎么办? 好消息是,如果使用正确的参数调用大多数记录器,包括Log4j和Logback,它们将使用堆栈跟踪编写异常。

Pass in the exception object as the last argument to the message, without a formatting directive. So if you used Log4j or Logback with the sample code like this:

logger.error(“发生了什么坏事:”,npe);

您会在日志文件中看到以下内容:

不好的事情发生了: java.lang.NullPointerException:糟糕! 在com.ericgoebelbecker.stacktraces.StackTrace.d(StackTrace.java:28) 在com.ericgoebelbecker.stacktraces.StackTrace.c(StackTrace.java:24) 在com.ericgoebelbecker.stacktraces.StackTrace.b(StackTrace.java:20) 在com.ericgoebelbecker.stacktraces.StackTrace.a(StackTrace.java:16) 在com.ericgoebelbecker.stacktraces.StackTrace.main(StackTrace.java:9)

您可以对异常和堆栈跟踪进行的最好的操作之一就是记录它们,以便可以使用它们来隔离问题。 如果您习惯打印有用的日志消息,其中包含堆栈跟踪和日志索引等详细信息,则搜索工具(例如Scalyr)将成为故障排除工具包中最强大的工具之一。

Java调试器

调试器通过控制程序的运行时并让您观察和控制它来进行工作。 为此,它向您显示了程序堆栈,并使您可以在任一方向上对其进行遍历。 在调试器中,与查看日志消息中的堆栈跟踪信息相比,您可以获得更完整的堆栈框架图。

让我们进行一些小的代码更改,然后将示例代码放入调试器。

首先,将局部变量添加到d()方法中:

静态void d(){   字符串消息=“糟糕”。   抛出新的NullPointerException(message); }

然后添加一个断点,其中d()在调试器中引发异常。 我正在为此图像使用IntelliJ的调试器。

在这里您可以看到我们添加到d()的字符串是堆栈框架的一部分,因为它是一个局部变量。 调试器在Stack内部运行,并为您提供每帧的详细图片。

强制线程转储

线程转储是很棒的事后分析工具,但是它们对于运行时问题也很有用。 如果您的应用程序停止响应或消耗的CPU或内存超出您的预期,则可以通过以下方式检索有关正在运行的应用程序的信息:jstack。

修改main()以便应用程序运行直到被杀死:

公共静态void main(String [] args)引发异常{   尝试{       while(true){           Thread.sleep(1000);       }   }抓(NullPointerException ice){       ice.printStackTrace();   } }

运行该应用程序,确定其pid,然后运行jstack。 在Windows上,您需要按Ctrl中断在DOS窗口中,您正在其中运行代码。

$ jstack <pid>

Jstack将产生大量输出。

too long

我的应用程序正在运行11个线程,而jstack为所有这些线程生成了堆栈跟踪。 第一个线程(有用地命名为main)是我们关注的那个线程。 您可以看到它在wait()上处于休眠状态。

Java堆栈跟踪:您的路线图

A stack trace is more than just a picture inside your application. It's a snapshot of a moment in time that includes every step your code took to get there. There's no reason to dread seeing one in your logs because they're a gift from Java that tells you exactly what happened. Make sure you're logging them when an error crops up and send them to a tool like Scalyr so they're easy to find.

Now that you understand what a Java stack trace is and how to use it, take a look at your code. Are you throwing away critical information about errors and exceptions in your code? Is there a spot where a call to Thread.dumpstack() might help you isolate a recurring bug? Perhaps it's time to run your app through the debugger a few times with some strategically-chosen breakpoints.

from: https://dev.to//scalyr/java-stack-trace-understanding-it-and-using-it-to-debug-5a3a

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。