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问题

我正在分析进行线程转储的不同方法。下面是我正在研究的两个问题

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

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

  • 比较两者之间的线程转储输出,我发现方法2有以下缺点

  • 使用方法2记录的线程转储不能被开源线程转储分析器(如TDA)解析
  • 输出不包括本机线程id,本机线程id在分析高cpu问题时可能很有用(对吗?)
  • 还有吗
  • 如能就以下方面获得建议/意见,我将不胜感激

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

  • 有没有其他方法可以进行线程转储

  • 多谢各位

    编辑-

    1和2的组合方法似乎是可行的。我们可以在后台运行一个专用线程,并以线程转储分析器可以理解的格式在日志文件中打印线程转储。
    如果需要任何仅由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?