从运行的程序或Java转储中获取死锁检测

5

我有一段正在运行的Java软件出现了卡顿。我想要查看其中的情况,但不知道如何做。

是否有一种工具可以输入PID并告诉我每个线程当前所在位置,以及一些变量的值?我正在使用Linux操作系统。

我大致知道问题是什么,但仍有几种可能的情况,因此确定问题所在将会很好。

由于错误只在几天后才会出现,而且在调试过程中从未出现过,因此这是一个了解问题的独特机会。

有什么想法吗?


你能为下一次打开远程调试吗?例如:https://dev59.com/B3VC5IYBdhLWcg3w9GA9 - laher
3个回答

12

实际上,您可以尝试使用 visualvm 和其 线程监视插件。 您还将能够创建线程转储,查看线程堆栈跟踪和它们的状态。 您还可以使用 jconsole 来检测死锁。 这两个工具都是JDK的一部分。 JConsole

这里 有关于如何使用visualvm进行线程分析的更多信息。


4
您可以获取线程转储。您可以使用kill -3 PID,其中PID是您的进程ID。这将导致线程转储输出到程序的标准输出。这将显示每个线程正在做什么,但不会提供有关变量的任何信息。无论如何,线程转储非常有用,建议您从那里开始。如果您仍然无法解决问题,可以使用类似jmap(JVM工具,免费但更难使用)或YourKit(付费产品但非常好)来获取内存快照,并检查变量。
一些关于jmap的信息: 使用jmap和jhat进行Java内存分析

kill -3 PID 似乎没有任何作用。JVM 在此之后仍然存活。这是怎么回事? - Franz Kafka
3
kill -3 不会真正杀死JVM,它只是发送一个信号来触发线程转储。线程转储将会输出到JVM的标准输出(而不是kill命令的标准输出)。请确保您正在将标准输出捕获到文件中。您是如何运行程序的?它是一个独立的应用程序,还是在像Tomcat这样的应用服务器中运行?例如,如果您正在使用Tomcat,则标准输出位于logs/catalina.out中。如果是独立的应用程序,您可以通过使用类似"java -jar myjar.jar > output.log"的命令来将标准输出重定向到某个文件中。希望这能帮到您。 - Andres Olarte
在您的独立案例中,如果您无法重新运行应用程序,因为它是生产环境并已经运行,那么如何将线程转储导向文件? - J.E.Y

0
在最近的JVM(OpenJDK/Oracle Java 7或更高版本)上,如果您使用VisualVM或jmap获取堆转储,它还包括当前所有正在运行的线程的堆栈转储,并带有指向堆中相应对象的链接。然后,您可以通过在VisualVM中打开堆转储来查看堆栈。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接