【问题标题】:Kill a stuck thread on a running VM (JBoss Instance) in Java?在 Java 中杀死正在运行的 VM(JBoss 实例)上的卡住线程?
【发布时间】:2011-01-21 19:16:31
【问题描述】:

bug in a third party library 在我的 JBoss 实例上的工作线程中导致无限循环。你知道在不重新启动服务器的情况下杀死这个“卡住”线程的方法吗?我们希望能够从中恢复,直到部署修复程序,最好不必重新启动。

我见过几个人 mention using Thread.interrupt() - 如果我要编写自己的 MBean,我将如何获取相关线程的句柄以中断它?

更新:无法使用任何这些方法解决。我确实遇到了another thread about the same issue,它有一个链接到为什么Thread.stop() is deprecated。其他人的asked a similar question 也有类似的结果。似乎更复杂的容器应该提供这种健康机制,但我猜他们的双手与 JVM 捆绑在一起。

【问题讨论】:

    标签: java jboss monitoring recovery


    【解决方案1】:

    我在第 3 方库中遇到了类似的错误(无限循环)。我最终自己应用了修复程序(同时等待来自 3rd 方库的人修复他们的烂摊子),然后我将修改后的 .class 放在我的 .war 中,确保它在伪造的 .class 之前加载(伪造的在伪造的第三方 .jar 中)。

    这不是很好,但它有效,请在此处查看我的问题:

    Order of class loading from a .war file

    我的意思是:如果您必须等待负责第 3 方窃听库的人员来修复他们的东西,您可能会等待 非常 很长时间。我们负担不起。我们需要尽快修复。所以我们最终对他们的代码应用了补丁/hack。

    例如,您可以在无限循环中添加一个布尔检查,然后在您希望虚假线程“死亡”时强制循环退出。

    请注意,我已经十年没有使用过已弃用的线程stop(),我真的不想在上述情况下使用它。

    【讨论】:

    • 同意回复:不等待第三方开发人员修复它,我只是说在很短的时间内(接下来的几天)等待我们的补丁通过测试进行审查。感谢他们提供的程序化修复选项,听起来不错 - 我真的在寻找内置的恢复选项。我不敢相信没有办法杀死一个你知道是恶性的线程!
    【解决方案2】:

    我想最困难的部分是识别挂线。您没有提供有关它的信息,但也许您可以围绕线程名称或其当前堆栈跟踪构建一些规则。

    如果您可以通过名称识别线程,我将通过使用Thread.currentThread().getThreadGroup() 获取我自己的线程组来获取 VM 中的所有线程,然后通过在线程组上调用 getParent() 来遍历线程组层次结构,直到它返回null。您现在拥有顶级线程组。您现在可以使用顶级线程组上的enumerate(Thread[] list) 方法用所有线程填充预分配的数组。

    如果您仍然需要堆栈跟踪来识别线程,您还可以使用静态实用程序方法Map<Thread,StackTraceElement[]> Thread.getAllStackTraces() 来获取所有线程。然而,计算堆栈跟踪非常昂贵,因此如果您实际上不需要它们,这可能不是最佳解决方案。

    识别出线程后,您必须对其调用stop() 方法。中断它不会有帮助,除非正在运行的代码的实现实际上评估了线程的中断标志并按照您的预期运行。并不是说 stop() 方法已被弃用,并且使用它可能会产生许多有趣的副作用。您可以在 API 文档中找到更多详细信息。

    【讨论】:

    • 我已经通过 VisualVM 中的 ThreadDump 识别了它。我确切地知道它是什么——但在代码中得到它是另一回事。您建议获取 threadGroup 然后向上走的方法听起来可行,但我需要线程的实际实例句柄才能在其上调用 stop() 或 interrupt()。
    • @cwash - enumerate 方法返回实际的线程实例。传入的数组用找到的所有 Thread 实例填充。如果您知道线程 ID,则可以遍历此数组以查找具有匹配 ID 的线程。请注意, enumerate() 方法具有奇怪的语义(它不会告诉您是否溢出),因此要使其全部工作很棘手。请注意,您可以使用 ThreadGroup.getActiveCount() 来初步猜测数组大小。
    • @cwash - 在此处查看一些示例:nadeausoftware.com/articles/2008/04/…
    【解决方案3】:

    您可以使用不推荐的 myThread.stop() 方法。但是很有可能线程仍然在那里被引用,所以你应该使用一些反射魔法从持有它的组件中删除对这个线程的所有引用。

    如何找到线程?使用 Thread.getThreadGroup() 和 ThreadGroup.getThreadGroup() 向上到根 ThreadGroup(),然后使用 iterate() 函数遍历所有线程。

    【讨论】:

    • 听起来可行,但我想我必须尝试一下。不知道任何已经按名称看起来像线程的东西?你用过 iterate() 对线程进行排序吗?
    【解决方案4】:

    试试我的jkillthread,它会尝试做这样的事情。

    【讨论】:

      猜你喜欢
      • 2020-12-23
      • 1970-01-01
      • 1970-01-01
      • 2018-12-10
      • 2012-05-31
      • 1970-01-01
      • 2012-06-12
      • 1970-01-01
      相关资源
      最近更新 更多