22

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

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

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

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

  1. 使用方法 2 记录的线程转储无法被 TDA 等开源线程转储分析器解析
  2. 输出不包括在分析高 CPU 问题时可能有用的本机线程 ID(对吗?)
  3. 还有吗?

我很高兴得到有关的建议/意见

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

  2. 还有其他方法来进行线程转储吗?

谢谢你。

编辑 -

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

4

4 回答 4

34

您可以使用

jstack {pid} > stack-trace.log

以用户身份在进程运行的盒子上运行。

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


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

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

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

于 2013-01-02T09:45:53.017 回答
8

在 Java 8 中,jcmd 是首选方法。

jcmd <PID> Thread.print

以下是Oracle 文档的片段:

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

但是,将其与应用程序一起提供可能会涉及许可问题,我不确定。

于 2016-12-14T16:35:02.060 回答
6

如果它是*nix,我会尝试kill -3 <PID>,但是您需要知道进程ID,也许您无权访问控制台?

于 2013-01-02T08:35:35.383 回答
1

如果有这样的环境,我建议您在暂存环境中进行所有堆分析,然后在生产中反映您所需的应用程序服务器调整(如果有)。如果您需要转储来分析应用程序的内存利用率,那么也许您应该考虑对其进行分析以进行更好的分析。

堆转储通常是由于OutOfMemoryExceptions内存泄漏和错误的内存管理而产生的。

检查您的应用程序服务器的文档,除了我前面提到的正常原因之外,大多数现代服务器都有在运行时生成转储的方法,但是生成的转储可能是特定于供应商的。

于 2013-01-02T08:42:32.837 回答