我正在分析获取线程转储的方法之间的差异。以下是我正在研究的几个人
定义一个jmx bean,它在单击声明的bean操作时通过Runtime.exec()触发jstack。
守护程序线程在预定义的时间间隔后重复执行“ManagementFactory.getThreadMXBean()。dumpAllThreads(true,true)”。
比较两者之间的线程转储输出,我在方法2中看到了以下缺点
我很高兴收到
的建议/意见在生产代码中通过Runtime.exec()执行jstack是否有任何缺点?各种操作系统上的兼容性问题 - windows,linux?
采取线程转储的其他方法吗?
谢谢。
修改
1和2的组合方法似乎是要走的路。我们可以在后台运行专用线程,并以线程转储分析器可以理解的格式在日志文件中打印线程转储。 如果需要任何额外的信息(比如说可能是本机线程id)只能由jstack输出记录,我们会根据需要手动执行。
答案 0 :(得分:32)
您可以使用
jstack {pid} > stack-trace.log
在进程正在运行的框中以用户身份运行。
如果您多次运行此操作,则可以使用diff
更轻松地查看哪些线程处于活动状态。
为了分析堆栈跟踪,我在专用线程中定期使用以下采样。</ p>
Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
使用此信息,您可以获取线程的id,运行状态并比较堆栈跟踪。
答案 1 :(得分:7)
使用Java 8,jcmd是首选方法。
jcmd <PID> Thread.print
以下是Oracle documentation的摘要:
JDK 8的发布引入了Java Mission Control,Java Flight Recorder和jcmd实用程序,用于诊断JVM和Java应用程序的问题。 建议使用最新的实用程序jcmd代替以前的jstack实用程序,以增强诊断并降低性能开销。
但是,将此与应用程序一起发送可能会产生许可问题,我不确定。
答案 2 :(得分:4)
如果它是* nix我会尝试kill -3 <PID>
,但是你需要知道进程ID,也许你无法访问控制台?
答案 3 :(得分:0)
如果有这样的环境,我建议你在暂存环境中进行所有堆分析,然后反映你所需的Application Server调整生产(如果有的话)。如果您需要转储来分析应用程序的内存利用率,那么您可能应该考虑对其进行分析以获得更好的分析。
堆转储通常是由于内存泄漏和内存管理不良导致的OutOfMemoryExceptions
生成的。
检查Application Server的文档,大多数现代服务器都有在运行时生成转储的方法,除了我之前提到的正常原因,结果转储可能是特定于供应商的。