记spring-boot项目启动卡住问题排查记录

问题背景

一个spring boot开发的项目,spring boot版本是1.5.7,携带的spring版本是4.1.3。开发反馈,突然在本地启动不起来了,表象特征就是在本地IDEA上运行时,进程卡住也不退出,应用启动时加载相关组件的日志也不输出。症状如下图:

问题分析

因为没有有用的日志信息,所以不能从日志这个层面上排查问题。但是像这种没有输出日志的话,一般情况下,肯定是程序内部启动流程卡在什么地方了,只能通过打印下当前线程堆栈信息了解下。一般情况下,在服务器环境,我们会使用java工具包中的jstack 工具来查看:如jstack pid(应用java进程)。

但是,在IDEA本地开发的话,IDEA内置了一个工具,可以直接查看当前应用的线程上线文信息,如:

注意下面那个箭头指向的像照相机一样的图标,故图思意,就是打印当前线程快照的的意思。点击后,就出现了右边那些线程上下文信息了,可以看到有很多的线程,我们主要关注下main线程,线程状态确实是waiting的,接着点击箭头所指向的main线程,可以看到如下内容:

"[email protected]" prio=5 tid=0x1 nid=NA waiting
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Unsafe.java:-1)
at java.util.concurrent.locks.LockSupport.park(www.ztyLegw.cn  LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
at java.util.concurrent.CountDownLatch.await(www.wanhaoptdL.com CountDownLatch.java:231)
at org.springframework.boot.autoconfigure.BackgroundPreinitializer.onApplicationEvent(BackgroundPreinitializer.java:63)
at org.springframework.boot.autoconfigure.BackgroundPreinitializer.onApplicationEvent(BackgroundPreinitializer.java:45)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:158)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
at org.springframework.boot.context.event.EventPublishingRunListener.finished(EventPublishingRunListener.java:115)
at org.springframework.boot.SpringApplicationRunListeners.www.tcgjgw.com callFinishedListener(SpringApplicationRunListeners.java:79)
at org.springframework.boot.SpringApplicationRunListeners.finished(SpringApplicationRunListeners.java:72)
at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:745)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:134)
- locked <0xea6> (a java.util.concurrent.atomic.AtomicBoolean)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.www.chaoyuL.com bootstrapServiceContext(BootstrapApplicationListener.java:175)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:98)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:64)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:74)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:325)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:296)
at cn.keking.project.customerManagement.KekingCustomerManagement.main(KekingCustomerManagement.java:36)

可以看到是通过CountDownLatch.await()阻塞了线程,接着看下面那行,所在代码块如下:


private static final CountDownLatch preinitializationComplete = new CountDownLatch(1);

@Override
public void onApplicationEvent(SpringApplicationEvent event) {
   if (event instanceof ApplicationEnvironmentPreparedEvent) {
      if (preinitializationStarted.compareAndSet(false, true)) {
         performPreinitialization();
      }
   }
   if (event instanceof ApplicationReadyEvent |www.chengmyuLegw.cn| event instanceof ApplicationFailedEvent) {
      try {
         preinitializationComplete.await();
      }
      catch (InterruptedException ex) {
         Thread.currentThread(www.cmylwg.com/).interrupt();
      }
   }
}

这是spring boot中的一个安全初始化资源的一个类,代码所示为监听SpringApplicationEvent事件,可以肯定的是,它的逻辑执行到了 preinitializationComplete.await();这里,导致了线程阻塞了。正常情况下,spring会触发ApplicationEnvironmentPreparedEvent事件完成资源的初始化,这里先不深究Spring为什么这么做,主要通过程序逻辑看下为什么卡这里了,在preinitializationComplete.await();所在行打个断点,看下event对象里的信息,如下:

原来event是一个Spring上下文初始化失败的异常事件对象,对象里包含了具体的异常信息,如箭头所指,关键异常信息如:

NoSuchMethodError:"org.springframework.util.ObjectUtils.unwrapOptional(Ljava/lang/Object;)Ljava/lang/Object;"

假设问题

通过上面的分析,基本定位到Spring boot应用启动卡住这个表象背后的真实原因了,而且也定位到了异常信息。

出现NoSuchMethodError异常,是因为调用方法的时候,找不到方法了。一般出现在两个有关联的jar包,但是版本对不上了,也就是常说的jar版本依赖冲突。查看了下,ObjectUtils是spring-core包里的一个类,当前的4.1.3版本确实没有这个unwrapOptional方法,spring-core-5.x的版本才新增了这个方法。因为之前的依赖是没有问题,为什么现在spring上下文会调用5.x的版本的方法呢?

所以先假设近期有开发在pom.xml里添加了新的的依赖,导致了这个问题。

小心求证

有了找问题的方向就好办了,因为代码都是git管理维护的,所以查看下pom.xml文件近期的提交记录即可,查看后,确实发现了近期对pom.xml有改动,添加了一个依赖:


<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.6.RELEASE<www.yuntianyuL.cn /version>
</dependency>

这里还涉及到一点Maven依赖优先级的问题,在pom.xml里直接这样添加的依赖优先于其他jar中pom.xml依赖的,也就是说,即使spring boot1.5.7自带了Spring-context.4.1.3,但是这样指定后,应用最后依赖的还是5.1.6的版本。具体的Maven依赖关系,可以参考我的博文《关于Maven的使用,这些你都了解了么?》。结合之前的分析,八九不离十了就是因为加了这个依赖导致的问题,spring-context.5.1.6配合spring-core.4.1.3肯定得出问题啊。直接移除这个依赖,然后启动系统一切正常,日志打印了Spring加载上线文的信息。

问题总结

定位这个问题的关键在于要了解java中线程堆栈的知识,在没有足够异常日志情况下通过线程快照排查问题。在定位到问题后,如NoSuchMethodError这样的异常,需要平时的经验积累来假设问题的真实原因,然后在追本溯源验明问题所在根本原因。找问题本质一定要这种循序渐进的思路。举例,出现这种问题,如果你直接去搜索引擎搜:“Spring boot应用启动卡住了”,是搜不出来什么东西的,但是当你发现了是由于jar冲突。去搜索引擎搜索:

“NoSuchMethodError:"org.springframework.util.ObjectUtils.unwrapOptional(Ljava/lang/Object;)Ljava/lang/Object;"”。就会有很多的内容,很容易解决问题。

原文地址:https://www.cnblogs.com/qwangxiao/p/10981911.html

时间: 2024-10-07 02:06:17

记spring-boot项目启动卡住问题排查记录的相关文章

spring boot 项目启动无任何反应

遇到的问题 spring boot项目启动后无任何报错,ps有进程,nohub无日志 定位 更换jar包,问题依然存在,将jar包放到其他服务器,运行正常,排除打包问题 同服务器其他系统运行正常,但停止后不能再次启动,出现相同问题 怀疑日志级别设置有问题,或编码问题,修改log配置问题依然存在 重启系统,问题仍然存在 重装jdk,问题解决 原文地址:https://www.cnblogs.com/bincoding/p/10199782.html

关于spring boot项目启动报错问题

这次用了spring boot,项目在启动时报错,由于我用的是jdk 1.7 ,该项目默认的是jdk 1.8,所以要把下面这一系列配置改好才行.废话不多说,上图: 一看发现,项目环境没有配全,打开file->Project Structuer,找到Project ,把里面的jdk配置成你自己的. 还有Modules里面的的这几项: 然后找到file->setting-->Java Compiler 里面 这些都配置好才能起动main函数启动服务.

记一次spring boot项目启动时的依赖循环

奇怪的是在我Ubuntu的机器上打包到测试服务器上报错,而从另外一台windows机器打包时就没问题,刚开始还以为是maven和jdk的问题.报错的启动时日志如下: 2019-06-14 14:03:45,644 org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter [main] (LoggingFailureAnalysisReporter.java:38) DEBUG --> Application faile

Spring boot 1: 使用IDEA创建Spring boot项目

项目用到的环境: Windows 10 JDK8 IntelliJ IDEA 2017.1.3 Apache Tomcat 8 Maven 3.3.3 使用IDEA新建spring boot项目 新建项目 选择类型为Spring Initializer. 填入相关的项目信息 选择denpendcy 接着下一步, 选择web. 选择路径 再下一步, 选择项目的路径, 点击完成 新建成的项目的文件目录结构如下图: 第一个Spring boot项目 pom.xml如下所示: <dependencies

docker部署spring boot项目在服务器上

IDE:idea 工具:docker spring boot:2.0.1 ======================================== 简单记录一下流程,以供参考: 第一步:首先得有一个spring boot的项目[集成了jpa+mybatis的spring boot 例子:https://github.com/AngelSXD/swapping] 第二步:项目打包为jar包 install成功以后 找到项目根目录下的target目录,这里面的jar就是打包好可以部署的jar

【spring cloud】导入一个新的spring boot项目作为spring cloud的一个子模块微服务,怎么做/或者 每次导入一个新的spring boot项目,IDEA不识别子module,启动类无法启动/右下角没有蓝色图标

如题:导入一个新的spring boot项目作为spring cloud的一个子模块微服务,怎么做 或者说每次导入一个新的spring boot项目,IDEA不识别,启动类无法启动,怎么解决 下面一起来走一遍这个流程: 1.将一个spring boot服务导入spring cloud中作为一个子模块 如图:这里有一个现成的spring cloud微服务集群,[如何创建一个spring cloud微服务:https://www.cnblogs.com/sxdcgaq8080/p/9035724.h

idea下新建Spring Boot项目并配置启动

一.操作步骤 ①使用idea新建一个Spring Boot项目 ②修改pom.xml ③修改application.properties ④修改编写一个Hello Spring Boot的Controller ⑤启动项目访问 二.详细步骤 1.File-->New-->Project 2.选择Spring Initializr 然后Next 3.输入Artiface 然后Next 4.勾选Web .模版我们选择官方推荐的Thymeleaf模版引擎,其他框架.中间件.数据库根据需要选择即可,而且

多个Spring Boot项目部署在一个Tomcat容器无法启动

Tomxin7 Simple, Interesting | 简单,有趣 本文将花费您五分钟时间 业务介绍 最近用Spring Boot开发了一个翻译的小项目,但是服务器上还跑着其他项目,包括一个同样用Spring Boot开发的微信后端服务,本次业务需要在阿里云的Linux使用同一个Tomcat容器部署多个项目. 部署环境:JDK8.Tomcat8.Centos7 遇到的问题 我多个项目一直都是部署在同一个Tomcat下,共用80端口,之前使用的MVC或者Servlet项目都没有问题,但是今天把

eclipse创建spring boot项目,tomcat启动成功,但http://localhost:8080无法访问报错404解决方案

spring boot的启动程序启动后,在访问http://localhost:8080地址的时候出现了错误,为什么出错网上我找了好久也没有得出具体的解决办法 当我指定到具体的action的时候,却可以正常的访问,目前一头懵逼. 原文地址:https://www.cnblogs.com/shifu8005/p/9862230.html