在生产环境中执行线程转储

2022-09-02 00:36:45

我正在分析获取线程转储的方法之间的差异。以下是我正在研究的几个

  1. 定义一个 jmx bean,它在单击声明的 bean 操作时通过 Runtime.exec() 触发 jstack。

  2. Daemon 线程在预定义的时间间隔后重复执行“ManagementFactory.getThreadMXBean().dumpAllThreads(true, true)”。

比较两者之间的线程转储输出,我看到了方法2的以下缺点

  1. 使用方法 2 记录的线程转储无法由开源线程转储分析器(如 TDA)解析
  2. 输出不包括本机线程 ID,这可能有助于分析高 CPU 问题(对吧?)
  3. 还有更多吗?

我很乐意获得有关以下方面的建议/意见

  1. 在生产代码中通过 Runtime.exec() 执行 jstack 有什么缺点吗?各种操作系统上的任何兼容性问题 - Windows,linux?

  2. 是否有任何其他方法可以获取线程转储?

谢谢。

编辑 -

1 和 2 的组合方法似乎是要走的路。我们可以让一个专用线程在后台运行,并以线程转储分析器可以理解的格式在日志文件中打印线程转储。如果需要任何额外的信息(比如说可能是本机线程ID),这些信息仅由jstack输出记录,我们会根据需要手动执行。


答案 1

您可以使用

jstack {pid} > stack-trace.log

以用户身份在运行进程的框中运行。

如果多次运行此命令,则可以使用 来更轻松地查看哪些线程处于活动状态。diff


为了分析堆栈跟踪,我在专用线程中定期使用以下示例。

 Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();

使用此信息,您可以获取线程的 ID、运行状态并比较堆栈跟踪。


答案 2

对于图片中的Java 8,jcmd是首选方法。

jcmd <PID> Thread.print

以下是来自 Oracle 文档的片段:

JDK 8 的发布引入了 Java Mission Control、Java Flight Recorder 和 jcmd 实用程序,用于诊断 JVM 和 Java 应用程序的问题。建议使用最新的实用程序 jcmd 而不是以前的 jstack 实用程序,以增强诊断并降低性能开销。

但是,随应用程序一起发布此内容可能会产生许可影响,我不确定。


推荐