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

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

1.单元测试类

@SpringBootTest(classes = {BareMetalApplication.class})
@RunWith(SpringRunner.class)
public class K8sUserNfsStoreInitServiceImplTest {

    @BeforeEach
    public void setUp() throws Exception {
        System.out.println("------------开始--------");
    }

    @AfterEach
    public void tearDown() throws Exception {
        System.out.println("------------结束--------");
    }

    @Test
    public 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后重新执行,三个方法都打印了,最后也正常关闭了

相关推荐

  1. 深入了解 Spring Boot 过程

    2024-07-09 20:58:04       31 阅读
  2. keil调试过程遇到问题及栈分析遇到问题

    2024-07-09 20:58:04       25 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-09 20:58:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-09 20:58:04       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-09 20:58:04       58 阅读
  4. Python语言-面向对象

    2024-07-09 20:58:04       69 阅读

热门阅读

  1. 王道考研数据机构:中缀表达式转为后缀表达式

    2024-07-09 20:58:04       31 阅读
  2. 基于深度学习的夜间图像修复

    2024-07-09 20:58:04       24 阅读
  3. SQL AND & OR 运算符的使用与区别

    2024-07-09 20:58:04       20 阅读
  4. VSCode中常用的快捷键

    2024-07-09 20:58:04       19 阅读
  5. C# —— File文件读写

    2024-07-09 20:58:04       24 阅读
  6. 工业路由器的应用

    2024-07-09 20:58:04       18 阅读
  7. 论文调研_物联网漏洞检测综述

    2024-07-09 20:58:04       23 阅读