【问题标题】:Java application dies silently, why?Java 应用程序无声无息地死掉,为什么?
【发布时间】:2015-11-03 12:31:26
【问题描述】:

我有一个 java 应用程序在日志中没有任何异常而神秘死亡。我通过 bash script 在后台运行它,它包装了如下的 nohup:

nohup java -Xms6g -Xmx6g -jar myapp.jar 2>> stderr.txt >> /dev/null & echo $! > /tmp/myapp-pid

Java 应用程序占用大量内存,因此配置了 6GB 堆空间(在 64 位 JVM 上运行)。它运行了大约 8 个小时,然后默默地死了。日志中没有异常,什么都没有。

应用程序从 main 方法进入无限循环,轮询 AWS SQS 以获取消息并处理它们。这一切都包含在一个 try-catch 中,我正在登录 catch。应用程序在完成一个 while 循环后似乎退出,因为它记录了最后一行。例如应用程序将始终以“已成功处理”结束。

while(true) {
    try {
        // Logic to poll SQS and process the message
    } catch (MyCustomException e) {
        // Write to SQS dead letter queue (was throwing at this point)
        // Delete message from original SQS
    } catch (Throwable e) {
        LOG.error(...);
    } finally { 
        LOG.info("Processing time was...");
    }
}

我不知道从哪里开始,因为我以为它会记录一些东西。谁能提供一些指针或一些 JVM 设置来配置以便我可以开始调查?

我想知道代码之外的东西是否可能导致错误。就像 JVM 崩溃一样?

更新 看起来这确实是一个编程错误。我不认为这是导致问题的原因,所以我没有将它添加到上面的代码路径中(现在刚刚添加),但我确实有另一个 catch 子句来捕获我创建的自定义异常。在那个捕获中,我试图将 SQS 消息移动到死信队列,但没有获得权限,因此被扔进了我没有处理的捕获中。

感谢所有帮助提出问题的人!

【问题讨论】:

  • 您的记录器是否配置为记录级别 ERROR - 而不仅仅是 INFO ?
  • 两个问题:你有一个日志就在“while”开始的地方吗?除了你提到的 8 小时,还有其他模式吗?
  • 从您的循环结构来看,我猜您在循环中的某处至少有一个 break; 命令...在这种情况下,请使用编辑器搜索并替换您的 @ 987654325@ 带有System.out.println("Breakng out of loop!");break; 之类的命令,以确认您是否通过这些中断之一退出循环;如果是,请继续调查哪个中断被错误触发以及原因。 --- 或者在每个break; 命令中添加断点,并使用分析器对其进行调试。
  • @tbsalling - 记录了错误,但信息级别不包括错误吗?
  • 我见过很多由于日志框架进行缓冲而导致日志文件未更新的情况。因此,只要您正在寻找错误,宁愿拥有太多日志而不是不完整的日志;-) 您可以稍后在修复错误时调整它。看看 -XX:ErrorFile 和 -XX:HeapDumpPath

标签: java terminate


【解决方案1】:

如果没有更多代码,很难说实际发生了什么。 但是根据 finally 的定义,它总是被执行,这也意味着在失败的情况下。也许你只是错过了之前写的异常。 尝试将 finally 调用移到“try”块内。

while(true) {
    try {
        // Logic to poll SQS and process the message
        LOG.info("Successfully processed");
    } catch (Throwable e) {
        //As mentioned in the comments try for debugging to log on info level here as well.
        // Maybe error level is disabled (although this should be 
        //very unlikely since error normally is written too when info is written.
        LOG.info(...);
    } finally { 
        //Clean up.
    }
}

这两个想法可以帮助您进一步调查您的问题。

【讨论】:

  • 抱歉,日志记录具有误导性。我实际上并没有在最后记录成功消息。我记录了处理时间。我得到了 INFO 和 ERROR 级别的日志,所以看起来很好。
【解决方案2】:

您的系统不会内存不足吗?尝试从包装脚本运行应用程序,记录退出代码 - echo $! >&2

同时运行 dmesg 可以告诉你 oom killer 是否选择了 ypur 应用程序作为受害者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多