您的位置:首页 > 财经 > 金融 > 单元测试Spring 上下文加载过程中遇到的阻塞或死锁问题

单元测试Spring 上下文加载过程中遇到的阻塞或死锁问题

2025/4/3 3:54:07 来源:https://blog.csdn.net/shenlf_bk/article/details/140219300  浏览:    关键词:单元测试Spring 上下文加载过程中遇到的阻塞或死锁问题

IDEA单元测试一直转圈,阻塞,前置后置的方法都不执行,无任何输出 

1.单元测试类

@SpringBootTest(classes = {BareMetalApplication.class})
@RunWith(SpringRunner.class)
public class K8sUserNfsStoreInitServiceImplTest {@BeforeEachpublic void setUp() throws Exception {System.out.println("------------开始--------");}@AfterEachpublic void tearDown() throws Exception {System.out.println("------------结束--------");}@Testpublic void userJuicefsStoreDeductionScheduleEndpoint() {System.out.println("------------执行--------");}
}

2.运行状态

2.1.无@RunWith注解和@SpringBootTest注解

正常执行,日志打印正常

2.2.有@RunWith注解和@SpringBootTest注解

单元测试启动,项目正常启动,定时任务,kafka正常执行,正常应该执行before>test>after并打印日志开始,结束,执行日志,但是一直转圈卡着不动。

 (ps:已经解决了我这里无法复现,随便找了个转圈的图)

3.使用JConsole工具分析线程堆栈

1)怀疑是定时任务,kafka造成的阻塞,一一关闭不管用

2)怀疑数据库死锁,排查无死锁

3)怀疑线程阻塞

只要有runwith和springboottest两个注解就无法加载。但是可以正常启动,卡在了启动后的一些执行上,线程阻塞或死锁可能性很大。

分析 JVM 中的线程状态,找出哪些线程阻塞或死锁。

例如jstack、jconsole、VisualVM等来检测是否存在阻塞或死锁情况。

3.1.打开终端,输入JConsole命令

 3.2.回车后弹出java监控和管理控制台

 页面如下图所示,选择本地连接,从列表中找到你的测试类,然后点击连接

 选择“线程”,查看main下的对栈信息,发现有阻塞。

 3.3.堆栈跟踪

名称: main
状态: java.util.concurrent.Semaphore$NonfairSync@7610436f上的TIMED_WAITING
总阻止数: 469, 总等待数: 163堆栈跟踪: 
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos(AbstractQueuedSynchronizer.java:1037)
java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1328)
java.util.concurrent.Semaphore.tryAcquire(Semaphore.java:409)
org.redisson.RedissonLock.lock(RedissonLock.java:121)
org.redisson.RedissonLock.lock(RedissonLock.java:69)
com.ly.baremetal.service.UserBareMetalInitService.safeUserBareMetalInitsMap(UserBareMetalInitService.java:88)
com.ly.baremetal.service.UserBareMetalInitService.handleReadyEvent(UserBareMetalInitService.java:167)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:789)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
com.ly.baremetal.service.UserBareMetalInitService$$EnhancerBySpringCGLIB$$c21d5b50.handleReadyEvent(<generated>)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:344)
org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:229)
org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:166)

这个堆栈跟踪显示了一个复杂的测试执行流程,涉及到多个层次的测试框架和引擎。关键点在于:

  • 测试启动时可能由于多个因素导致线程阻塞,主要集中在 RedissonLock 的锁等待和获取过程中。
  • Semaphore$NonfairSync TIMED_WAITING 状态表明某些线程在等待锁的许可证。 

从堆栈跟踪来看,确实显示了 UserBareMetalInitService.handleReadyEvent 方法在执行时出现了阻塞。具体原因可能是该方法内部的某些操作导致了阻塞,最终导致 SemaphoreTIMED_WAITING 状态。

可能的原因包括:

  1. RedissonLock的使用UserBareMetalInitService 中的 RedissonLock 被用于同步操作,可能在获取锁时发生了阻塞。

  2. 资源竞争:如果多个线程或服务同时竞争相同的资源,例如数据库连接或外部服务调用,也可能导致阻塞。

  3. 性能问题:某些操作可能耗时较长,例如复杂的计算、IO 操作或网络请求,这些都可能导致方法执行时间较长。

 阻塞代码所在行:

com.ly.baremetal.service.UserBareMetalInitService.safeUserBareMetalInitsMap(UserBareMetalInitService.java:88)
com.ly.baremetal.service.UserBareMetalInitService.handleReadyEvent(UserBareMetalInitService.java:167) 

3.4.代码定位

 3.5.分布式锁无法释放

3.6.手动释放锁

redis中删除问题key后重新执行,三个方法都打印了,最后也正常关闭了

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com