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
方法在执行时出现了阻塞。具体原因可能是该方法内部的某些操作导致了阻塞,最终导致 Semaphore
的 TIMED_WAITING
状态。
可能的原因包括:
RedissonLock的使用:
UserBareMetalInitService
中的RedissonLock
被用于同步操作,可能在获取锁时发生了阻塞。资源竞争:如果多个线程或服务同时竞争相同的资源,例如数据库连接或外部服务调用,也可能导致阻塞。
性能问题:某些操作可能耗时较长,例如复杂的计算、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后重新执行,三个方法都打印了,最后也正常关闭了