7

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

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

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

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

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

4

4 回答 4

9

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

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

于 2009-03-01T21:55:10.303 回答
2

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

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

(根据评论编辑)

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

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

于 2009-03-01T23:47:33.373 回答
1

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

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

于 2009-03-01T21:54:34.690 回答
1

我在类路径(JBPM)上有几个不同版本的库。使用 wrapper,您可以使用通配符来包含 jar。不过要小心这一点,因为您可能不小心包含了超出您应有的内容。

这是一篇 IBM 文章,其中提供了有关在 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。

于 2009-03-09T14:01:40.720 回答