莫向光明惰寸功 2024-04-03 22:01 采纳率: 0%
浏览 23
已结题

hprose-java导致应用退出原因

Springboot2.6.6,引入RPC工具hprose-java 2.0.9,偶尔会导致应用退出。
请各路大*神一起探讨一下其中的原理。

首先是应用不定时无故挂掉,发现无任何cpu、内存异常情况(有时半夜挂掉,根本没人访问),也监听了进程信号,不是linux系统(阿里云)主动kill,那就是应用自身退出的。最终我通过字节码技术在调用Shutdown.exit处,打印线程栈日志,发现了是hprose触发的。

img


查看hprose版本比较老,在应用启动时取当前线程或id=1的线程作为主线程,然后循环检查主线程状态,若不存活则调用System.exit。从而使应用退出。

img

img

img

我升级到最新版本并且禁用了hprose退出应用的逻辑。目前应用没再退出
我看hprose新版本这块已经被优化了,但还是想理清导致退出的原理。

疑问点:
我理解这个hprose设定的主线程,是登录请求应用时,用到了hprose,才进行初始化,那么当前请求线程也就是tomcat的线程池里的线程,并且是核心线程。登录就会触发hprose此时没有并发,tomcat不会产生非核心线程。
1、观点1:既然是核心线程,应该不会被销毁,除非是应用退出了。
2、观点2:linux系统层面销毁了该线程,但我不知其原理。
期望大*神能解释其中原理,感谢,有偿。

img

  • 写回答

17条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-03 22:01
    关注

    引自免费微信小程序:皆我百晓生

    针对您所描述的问题及提供的相关源代码片段,您怀疑您的Spring Boot应用因引入hprose-java库而发生不定时无故退出的现象。根据您所提供的线索,尤其是关于Threads.java文件中的关键代码段以及您提到的线程堆栈跟踪信息,我们可以推测导致应用退出的可能原因与hprose-java库中注册的关闭钩子(shutdown hook)有关。以下是对此问题的详细分析:

    问题概述

    Threads.java中,hprose-java库执行了以下操作:

    1. 获取主程序线程:在静态初始化块中,它遍历线程组层次结构找到根线程组,并确定当前运行的“主”线程(可能是ID为1的线程,或者是当前正在执行此代码的线程)。这里将该线程标识为mainThread

    2. 注册关闭钩子:提供了一个方法registerShutdownHandler用于注册一个默认的关闭处理器。当此方法被调用时,会向Java运行时环境添加一个关闭钩子,即一个在JVM即将退出时运行的线程。该钩子的目标是在JVM关闭时执行defaultHandler.run()

    3. 监测主程序线程状态:创建一个新的守护线程,该线程持续检查mainThread是否仍然存活。如果发现mainThread不再存活,则调用System.exit(0),强制终止整个应用程序。

    可能导致应用退出的原因

    基于上述分析,有以下几点可能导致您的应用意外退出:

    观点1:主程序线程被错误地判断为已停止

    根据您提供的代码片段,hprose-java库可能会将某个HTTP请求处理线程(如http-nio-8080-exec-1)误认为是主程序线程。当该线程由于某种原因暂时阻塞或进入空闲状态时,hprose创建的监控线程可能会误判为mainThread已停止,并因此调用System.exit(0)导致应用退出。这种情况符合您观察到的现象,即应用在无人访问时也可能突然退出。

    观点2:Linux系统层面影响

    虽然您提到未发现操作系统主动kill进程的情况,但在极少数情况下,操作系统资源管理策略(例如OOM Killer)或其他外部因素可能会影响到应用线程的状态,间接触发hprose的关闭逻辑。不过,从您提供的信息来看,这种可能性相对较小。

    解决措施与建议

    您已经提到通过升级至hprose-java的新版本并禁用退出应用的逻辑解决了问题。这表明新版库很可能已经修复了上述可能导致意外退出的逻辑。如果您需要进一步了解导致退出的具体原理,可以考虑以下步骤:

    1. 查看hprose-java更新日志:查阅hprose-java从旧版到您使用的最新版之间的变更记录,寻找与关闭钩子或线程监控相关的改进项。这有助于确认新版是如何优化这一部分逻辑的。

    2. 对比源代码差异:直接对比旧版和新版Threads.java及其他相关类的源代码,重点关注与关闭钩子注册、主程序线程识别及监控线程行为相关的改动。这样可以更直观地理解问题所在及修复方案。

    3. 监控线程状态:在生产环境中部署额外的日志记录或监控工具,以便在应用意外退出前捕获更多关于mainThread和其他相关线程状态的信息。这些数据可以帮助您验证之前的分析,并为排查其他潜在问题提供依据。

    综上所述,您的应用退出很可能是由于旧版hprose-java库中对主程序线程状态的误判导致的。升级至新版本并禁用相应逻辑后,问题得到解决。为进一步理解原理,您可以查阅库更新日志和对比源代码,同时加强线程状态监控以确保系统的稳定运行。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 4月10日
  • 创建了问题 4月3日

悬赏问题

  • ¥15 单纯型python实现编译报错
  • ¥15 c++2013读写oracle
  • ¥15 c++ gmssl sm2验签demo
  • ¥15 关于模的完全剩余系(关键词-数学方法)
  • ¥15 有没有人懂这个博图程序怎么写,还要跟SFB连接,真的不会,求帮助
  • ¥15 PVE8.2.7无法成功使用a5000的vGPU,什么原因
  • ¥15 is not in the mmseg::model registry。报错,模型注册表找不到自定义模块。
  • ¥15 安装quartus II18.1时弹出此error,怎么解决?
  • ¥15 keil官网下载psn序列号在哪
  • ¥15 想用adb命令做一个通话软件,播放录音