在生产中进行线程转储

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

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

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

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

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

我很感激获得建议/意见

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

  2. 采取线程转储的任何其他方法?

谢谢。

编辑 –

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

您可以使用

jstack {pid} > stack-trace.log 

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

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


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

  Map allStackTraces = Thread.getAllStackTraces(); 

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

使用Java 8,jcmd是首选方法。

 jcmd  Thread.print 

以下是Oracle文档的片段:

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

但是,随应用程序运送此产品可能会产生许可影响,我不确定。

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

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

堆转储通常是由于内存泄漏和内存管理不良导致的OutOfMemoryExceptions而生成的。

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