【问题标题】:Java appears hungJava 出现挂起
【发布时间】:2010-10-10 16:18:08
【问题描述】:

我在自定义应用程序中使用 Java 服务包装器已经有一段时间了,它运行良好。由于最近几天将我们的应用程序更新到新版本,JVM 开始挂起,然后包装器在日志中打印: JVM 出现挂起:等待来自 JVM 的信号超时。

然后它会自动终止 JVM 并再次启动应用程序。这会在运行大约 10 小时后发生,这使得调试变得更加困难。

当然,我会查看我们所做的更改,但没有进行我怀疑会导致此类问题的重大更改。

我在哪里可以尝试找出正在发生的事情?来自应用程序的调试消息并不表示任何有趣的事情。如果 JVM 只是崩溃,它通常会创建一个转储,这可以帮助调试它,但它会挂起,所以它不会创建一个转储。如果我让它不自动重新启动服务,在重新启动它之前我可以做些什么来从 JVM 中获取一些有用的信息?

在我看来,JVM 不应该因为典型的编程错误而挂起。在此之前您遇到过什么会导致 JVM 挂起的情况?

【问题讨论】:

    标签: java debugging freeze java-service-wrapper


    【解决方案1】:

    阅读wrapper.ping.timeout property。包装软件不时与您的 JVM 通信,以确保它处于活动状态。如果该通信由于某种原因失败,则包装器认为该进程已挂起并尝试重新启动它。

    根据您的应用程序的架构,当包装器尝试“ping”它时,您的 JVM 可能正忙于处理其他事情。

    【讨论】:

    • 增加属性可能会导致包装器没有注意到问题并且不会重新启动应用程序,但这只是解决问题的方法。在挂起期间,它不会响应客户端请求,这也不好。
    【解决方案2】:

    看看你是否可以使用Visual VM 看看发生了什么。让 Visual VM 全程监控应用程序,当它停止工作时,您或许可以确定问题所在。

    如果 VM 挂起,您可以获取线程的状态...我认为 Visual VM 会比通常的 ctrl-break(或任何组合键)更容易一些。

    (根据评论编辑)

    试过这个。上次挂了 线程数和数量 正在使用的内存非常低,所以 这些都没有导致 问题。不幸的是,它挂起后 包装器终止它你不能 获取线程转储。

    有没有什么方法可以在没有包装器的情况下运行它来调试它?此外,如果您使用 NetBeans 分析器,它可能会给您一个在它停止时处理它的机会(我将在今天晚些时候检查,看看我是否能发现它的行为是否会有所不同)。

    【讨论】:

    • 试过这个。上次它挂起的线程数和使用的内存量都非常低,所以这些都没有引起问题。不幸的是,在它挂起并且包装器终止它之后,您无法获得线程转储。
    【解决方案3】:

    你在什么环境?操作系统、JVM 版本、硬件架构?

    这听起来确实像一个错误,并且考虑到它需要很多小时,这听起来像是某种资源耗尽错误。

    【讨论】:

    • Linux RHEL4、Java 1.6.0、英特尔 32 位。我正在监视线程数和内存使用情况;到目前为止,它并没有使用太多。我们很少使用线程。我们只是在应用程序启动时启动一些,每隔几分钟查看一下是否有需要处理的内容。
    • 10 小时的一致性如何?实际上只有两种可能性:一些资源耗尽,或者随机死锁/延迟。什么样的应用程序?
    • 完全不一致。到目前为止,它只发生了 3 次。实际上,看起来平均值略高于 10 小时。它发生在12、14和19小时。我要尝试做的是将其设置为不自动重启,这样我就可以在它发生时稍微调查一下状态。
    • 好的,那么这就证明了一个随机事件。我很想将 ping 间隔设置为尽可能短,以便您可以更快地重复它。
    • 它也是随机发生的。我们有一些工作在固定时间运行,所以不是它们。这是一个独立的 Java 服务器应用程序。它接受来自客户端的 RMI 调用。它通过 Hibernate 与数据库通信。
    【解决方案4】:

    我在类路径 (JBPM) 上有几个不同版本的库。使用包装器,您可以使用通配符来包含罐子。不过要小心这一点,因为您可能会不小心包含过多的内容。

    这是一篇 IBM 文章,其中提供了有关 debugging hangs in Java 的信息。它基本上说有两件事会导致挂起:

    1. 无限循环,
    2. 僵局。

    从那以后,我不得不调试其他挂起的问题。在 linux 上,您可以向 JVM 发送 QUIT 信号,使其向控制台执行线程转储。这确实有助于找出问题所在。使用这个命令来做到这一点:kill -QUIT

    2017 年 6 月 13 日编辑

    这些天我使用JDK中包含的jmap来转储程序的整个内存。然后我使用 Eclipse Memory Analyzer 来查看程序崩溃时的确切状态。您可以查看处于活动状态的线程列表,然后检查每个堆栈帧中的变量。

    /usr/java/latest/bin/jmap -dump:file=/tmp/app-crash.hprof <PID>
    

    其中PID是java进程的进程ID。

    【讨论】:

      猜你喜欢
      • 2012-08-23
      • 1970-01-01
      • 2017-09-16
      • 2014-11-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      • 2013-10-19
      • 1970-01-01
      相关资源
      最近更新 更多