在生产中进行线程转储
我正在分析获取线程转储的方法之间的差异。 以下是我正在研究的几个人
-
定义一个jmx bean,它在单击声明的bean操作时通过Runtime.exec()触发jstack。
-
守护程序线程在预定义的时间间隔后重复执行“ManagementFactory.getThreadMXBean()。dumpAllThreads(true,true)”。
比较两者之间的线程转储输出,我在方法2中看到了以下缺点
- 使用方法2记录的线程转储无法由TDA等开源线程转储分析器解析
- 输出不包括本机线程ID,它可用于分析高CPU问题(对吗?)
- 还有吗?
我很感激获得建议/意见
-
在生产代码中通过Runtime.exec()执行jstack是否有任何缺点? 各种操作系统上的兼容性问题 – windows,linux?
-
采取线程转储的任何其他方法?
谢谢。
编辑 –
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的文档,大多数现代服务器都有在运行时生成转储的方法,除了我之前提到的正常原因,结果转储可能是特定于供应商的。