Java 在生产中进行线程转储
我正在分析进行线程转储的不同方法。下面是我正在研究的两个问题Java 在生产中进行线程转储,java,runtime.exec,thread-dump,Java,Runtime.exec,Thread Dump,我正在分析进行线程转储的不同方法。下面是我正在研究的两个问题 定义一个JMXbean,它在单击声明的bean操作时通过Runtime.exec()触发jstack 守护进程线程在预定义的间隔后重复执行“ManagementFactory.getThreadMXBean().dumpAllThreads(true,true)” 比较两者之间的线程转储输出,我发现方法2有以下缺点 使用方法2记录的线程转储不能被开源线程转储分析器(如TDA)解析 输出不包括本机线程id,本机线程id在分析高cpu问题
如果需要任何仅由jstack输出记录的额外信息(比如可能是本机线程id),我们会根据需要手动执行。如果是*nix,我会尝试
kill-3
,但是,您需要知道进程id,并且可能无法访问console?我建议您在登台环境中进行所有堆分析(如果有这样的环境),然后在生产环境中反映所需的应用程序服务器调优(如果有)。如果您需要转储来分析应用程序的内存利用率,那么也许您应该考虑对其进行分析,以便更好地分析。
堆转储通常是由内存泄漏和内存管理错误导致的OutOfMemoryExceptions
生成的
查看应用程序服务器的文档,除了我前面提到的正常原因外,大多数现代服务器都有在运行时生成转储的方法,但生成的转储可能是特定于供应商的。您可以使用
jstack {pid} > stack-trace.log
在进程运行的框中以用户身份运行
如果多次运行此选项,可以使用diff
查看哪些线程更容易激活
为了分析堆栈跟踪,我使用以下在专用线程中定期采样的数据
Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
Map allStackTraces=Thread.getAllStackTraces();
使用这些信息,您可以获得线程id、运行状态并比较堆栈跟踪。对于图中的Java 8,jcmd是首选方法
jcmd <PID> Thread.print
jcmd Thread.print
以下是中的代码段:
JDK 8的发布引入了Java任务控制、Java飞行记录器和用于诊断JVM和Java应用程序问题的jcmd实用程序建议使用最新的实用程序jcmd,而不是以前的jstack实用程序,以增强诊断功能并减少性能开销。
但是,随应用程序一起交付可能会涉及许可问题,我不确定。这是否与JEE应用程序有关?是的。访问控制台和获取进程id是“kill”方法的问题。我上面提到的方法没有这些缺点。我了解获取线程转储的开销,但为了清楚地了解生产环境中发生的事情,我们需要此功能。我们使用glassfish应用服务器,在glassfish中获得线程转储并没有什么特别的。您需要向jvm发送一个kill信号,这在我对@Peter Lljenbery的回复中提到了两个缺点。明白了,那么我建议您使用一个启用内存转储的特殊构建(可能通过配置),并评估您的评估,然后在完成后禁用它。这样,您就不必担心使用jstack或任何其他类似方法的影响。实际上,jstack在这种情况下是可以的。你也应该看看这个,它可能有点帮助(滚动到描述部分)。所以你推荐我上面描述的方法2?你对我上面提到的缺点有什么看法?另外,您认为在生产环境中执行runtime.exec()会有任何问题吗?相反,我是说jstack会根据您的情况完成这项工作,我只是建议您在应用程序中添加一些方法,通过这些方法可以根据需要触发这些转储,并且有一个配置来同时禁用此功能。您不想让它在生产中可用。执行jstack的第一点与我上面提到的方法1相同吗?通过jmx集成和触发它可以帮助用户不必担心进程id。同样,通过jmx方法,我们可以安排在每个指定的间隔后重复执行jstack。关于调用Thread.getAllStackTraces()的第二点;这意味着我必须手动记录线程转储,以便线程转储分析器对其进行解释。与您提到的第一种方法相比,这种方法有什么好处?我会在程序中使用分析仪,只记录您感兴趣的信息。在我的例子中,只有当我遇到问题时才会发生这种情况,这通常意味着我想看看当时发生了什么其他日志,例如,它是什么时候发生的,线程记录的最后一件事情是什么,以及之后产生的错误。很高兴知道这一点。它们可以被TDA这样的开源线程转储分析器解析吗?它们是否包含本机线程id?