两个单例的EJB相互调用死锁
Deadlock in EJB mutual invocation of two singletons
我有 2 个 EJB @Singleton
s,它们在 tomee运行
他们互相调用,陷入僵局
@Startup
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DeadlockReproducer {
private final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, this.getClass());
@EJB
private DeadlockReproducerAid deadlockReproducerAid;
@PostConstruct
public void reproduce(){
LOGGER.info("reproduce");
deadlockReproducerAid.lockMe();
}
public void youCantGetMe(){
LOGGER.info("youCantGetMe");
}
}
@Startup
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DeadlockReproducerAid {
private final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, this.getClass());
@EJB
DeadlockReproducer deadlockReproducer;
public void lockMe(){
LOGGER.info("lockMe");
deadlockReproducer.youCantGetMe();
}
}
当 youCantGetMe 等待复制到 return 时,我遇到了死锁。
这是堆栈跟踪:
"localhost-startStop-1" #68 daemon prio=5 os_prio=0 tid=0x0000000056d1f000 nid=0x14e0 waiting on condition [0x0000000058aab000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000fc7a2cc8> (a java.util.concurrent.FutureTask)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
at java.util.concurrent.FutureTask.get(FutureTask.java:191)
at org.apache.openejb.core.singleton.SingletonInstanceManager.getInstance(SingletonInstanceManager.java:112)
at org.apache.openejb.core.singleton.SingletonContainer.invoke(SingletonContainer.java:200)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod(EjbObjectProxyHandler.java:308)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbObjectProxyHandler.java:303)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectProxyHandler.java:92)
at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:308)
at com.company.test.eu.logic.server.stateMachine.DeadlockReproducer$$LocalBeanProxy.youCantGetMe(com/company/test/eu/logic/server/stateMachine/DeadlockReproducer.java)
at com.company.test.eu.logic.server.stateMachine.DeadlockReproducerAid.lockMe(DeadlockReproducerAid.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:192)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:173)
at org.apache.openejb.monitoring.StatsInterceptor.record(StatsInterceptor.java:181)
at org.apache.openejb.monitoring.StatsInterceptor.invoke(StatsInterceptor.java:100)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:192)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:173)
at org.apache.openejb.core.interceptor.InterceptorStack.invoke(InterceptorStack.java:85)
at org.apache.openejb.core.singleton.SingletonContainer._invoke(SingletonContainer.java:256)
at org.apache.openejb.core.singleton.SingletonContainer.invoke(SingletonContainer.java:212)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod(EjbObjectProxyHandler.java:308)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbObjectProxyHandler.java:303)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectProxyHandler.java:92)
at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:308)
at com.company.test.eu.logic.server.stateMachine.DeadlockReproducerAid$$LocalBeanProxy.lockMe(com/company/test/eu/logic/server/stateMachine/DeadlockReproducerAid.java)
at com.company.test.eu.logic.server.stateMachine.DeadlockReproducer.reproduce(DeadlockReproducer.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:192)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$LifecycleInvocation.invoke(ReflectionInvocationContext.java:223)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:173)
at org.apache.openejb.monitoring.StatsInterceptor.record(StatsInterceptor.java:181)
at org.apache.openejb.monitoring.StatsInterceptor.PostConstruct(StatsInterceptor.java:109)
at sun.reflect.GeneratedMethodAccessor37.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:192)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:173)
at org.apache.openejb.core.interceptor.InterceptorStack.invoke(InterceptorStack.java:85)
at org.apache.openejb.BeanContext.newInstance(BeanContext.java:1590)
at org.apache.openejb.core.singleton.SingletonInstanceManager.createInstance(SingletonInstanceManager.java:179)
at org.apache.openejb.core.singleton.SingletonInstanceManager.access0(SingletonInstanceManager.java:69)
at org.apache.openejb.core.singleton.SingletonInstanceManager.call(SingletonInstanceManager.java:120)
at org.apache.openejb.core.singleton.SingletonInstanceManager.call(SingletonInstanceManager.java:118)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.openejb.core.singleton.SingletonInstanceManager.getInstance(SingletonInstanceManager.java:129)
at org.apache.openejb.core.singleton.SingletonInstanceManager.initialize(SingletonInstanceManager.java:93)
at org.apache.openejb.core.singleton.SingletonInstanceManager.start(SingletonInstanceManager.java:84)
at org.apache.openejb.core.singleton.SingletonContainer.start(SingletonContainer.java:125)
at org.apache.openejb.assembler.classic.Assembler.startEjbs(Assembler.java:1168)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:807)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:623)
at org.apache.tomee.catalina.TomcatWebAppBuilder.startInternal(TomcatWebAppBuilder.java:1248)
at org.apache.tomee.catalina.TomcatWebAppBuilder.configureStart(TomcatWebAppBuilder.java:1087)
at org.apache.tomee.catalina.GlobalListenerSupport.lifecycleEvent(GlobalListenerSupport.java:130)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5378)
- locked <0x00000000e1115938> (a org.apache.catalina.core.StandardContext)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
- locked <0x00000000e1115938> (a org.apache.catalina.core.StandardContext)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1083)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1880)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- <0x00000000fb344d08> (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync)
- <0x00000000e0bca828> (a java.util.concurrent.ThreadPoolExecutor$Worker)
当 public void reproduce()
被 @PostConstruct
注释调用时,它们会死锁。
当它被另一个 bean 调用时,youCantGetMe
执行 return。
例如,以下设置有效:
@Startup
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DeadlockReproducer {
private final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, this.getClass());
@EJB
private DeadlockReproducerAid deadlockReproducerAid;
//@PostConstruct - no postconstruct now
public void reproduce(){
LOGGER.info("reproduce");
deadlockReproducerAid.lockMe();
}
public void youCantGetMe(){
LOGGER.info("youCantGetMe");
}
}
@Startup
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DeadlockReproducerAid {
private final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, this.getClass());
@EJB
DeadlockReproducer deadlockReproducer;
public void lockMe(){
LOGGER.info("lockMe");
deadlockReproducer.youCantGetMe();
}
}
@Startup
@Singleton
public class DeadlockInvoker {
@EJB
DeadlockReproducer deadlockReproducer;
@PostConstruct
public void startup(){
deadlockReproducer.reproduce();
}
}
为什么会这样,我怎样才能在不借助外部调用程序的情况下使它工作?
编辑:
我开始发现这种行为与 EJB 中的单例生命周期有关。
单例在 @PostConstruct
完成 运行 之前不会进入 Ready
状态,并且可能当它的状态不是 Ready
时,它不会响应外部方法调用。
您需要标记您的第一个 ejb 需要第二个在它之前启动:https://docs.oracle.com/javaee/6/api/javax/ejb/DependsOn.html
除此之外,我没有发现代码有任何问题,单例使用可重入锁,所以这应该可以工作。
我猜这个行为与 EJB 中的单例生命周期有关。
我用第三个启动 bean 解决了这个问题,它依赖于两个单例,并在两个单例都已加载时手动调用其中一个单例的 start()
方法。为此,我添加了 start()
方法。
我本可以从 DeadlockReproducerAid
开始 DeadlockReproducer
,但这会掩盖第二个 class 的目的。
我有 2 个 EJB @Singleton
s,它们在 tomee运行
他们互相调用,陷入僵局
@Startup
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DeadlockReproducer {
private final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, this.getClass());
@EJB
private DeadlockReproducerAid deadlockReproducerAid;
@PostConstruct
public void reproduce(){
LOGGER.info("reproduce");
deadlockReproducerAid.lockMe();
}
public void youCantGetMe(){
LOGGER.info("youCantGetMe");
}
}
@Startup
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DeadlockReproducerAid {
private final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, this.getClass());
@EJB
DeadlockReproducer deadlockReproducer;
public void lockMe(){
LOGGER.info("lockMe");
deadlockReproducer.youCantGetMe();
}
}
当 youCantGetMe 等待复制到 return 时,我遇到了死锁。
这是堆栈跟踪:
"localhost-startStop-1" #68 daemon prio=5 os_prio=0 tid=0x0000000056d1f000 nid=0x14e0 waiting on condition [0x0000000058aab000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000fc7a2cc8> (a java.util.concurrent.FutureTask)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
at java.util.concurrent.FutureTask.get(FutureTask.java:191)
at org.apache.openejb.core.singleton.SingletonInstanceManager.getInstance(SingletonInstanceManager.java:112)
at org.apache.openejb.core.singleton.SingletonContainer.invoke(SingletonContainer.java:200)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod(EjbObjectProxyHandler.java:308)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbObjectProxyHandler.java:303)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectProxyHandler.java:92)
at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:308)
at com.company.test.eu.logic.server.stateMachine.DeadlockReproducer$$LocalBeanProxy.youCantGetMe(com/company/test/eu/logic/server/stateMachine/DeadlockReproducer.java)
at com.company.test.eu.logic.server.stateMachine.DeadlockReproducerAid.lockMe(DeadlockReproducerAid.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:192)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:173)
at org.apache.openejb.monitoring.StatsInterceptor.record(StatsInterceptor.java:181)
at org.apache.openejb.monitoring.StatsInterceptor.invoke(StatsInterceptor.java:100)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:192)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:173)
at org.apache.openejb.core.interceptor.InterceptorStack.invoke(InterceptorStack.java:85)
at org.apache.openejb.core.singleton.SingletonContainer._invoke(SingletonContainer.java:256)
at org.apache.openejb.core.singleton.SingletonContainer.invoke(SingletonContainer.java:212)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod(EjbObjectProxyHandler.java:308)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbObjectProxyHandler.java:303)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectProxyHandler.java:92)
at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:308)
at com.company.test.eu.logic.server.stateMachine.DeadlockReproducerAid$$LocalBeanProxy.lockMe(com/company/test/eu/logic/server/stateMachine/DeadlockReproducerAid.java)
at com.company.test.eu.logic.server.stateMachine.DeadlockReproducer.reproduce(DeadlockReproducer.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:192)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$LifecycleInvocation.invoke(ReflectionInvocationContext.java:223)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:173)
at org.apache.openejb.monitoring.StatsInterceptor.record(StatsInterceptor.java:181)
at org.apache.openejb.monitoring.StatsInterceptor.PostConstruct(StatsInterceptor.java:109)
at sun.reflect.GeneratedMethodAccessor37.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:192)
at org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:173)
at org.apache.openejb.core.interceptor.InterceptorStack.invoke(InterceptorStack.java:85)
at org.apache.openejb.BeanContext.newInstance(BeanContext.java:1590)
at org.apache.openejb.core.singleton.SingletonInstanceManager.createInstance(SingletonInstanceManager.java:179)
at org.apache.openejb.core.singleton.SingletonInstanceManager.access0(SingletonInstanceManager.java:69)
at org.apache.openejb.core.singleton.SingletonInstanceManager.call(SingletonInstanceManager.java:120)
at org.apache.openejb.core.singleton.SingletonInstanceManager.call(SingletonInstanceManager.java:118)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.openejb.core.singleton.SingletonInstanceManager.getInstance(SingletonInstanceManager.java:129)
at org.apache.openejb.core.singleton.SingletonInstanceManager.initialize(SingletonInstanceManager.java:93)
at org.apache.openejb.core.singleton.SingletonInstanceManager.start(SingletonInstanceManager.java:84)
at org.apache.openejb.core.singleton.SingletonContainer.start(SingletonContainer.java:125)
at org.apache.openejb.assembler.classic.Assembler.startEjbs(Assembler.java:1168)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:807)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:623)
at org.apache.tomee.catalina.TomcatWebAppBuilder.startInternal(TomcatWebAppBuilder.java:1248)
at org.apache.tomee.catalina.TomcatWebAppBuilder.configureStart(TomcatWebAppBuilder.java:1087)
at org.apache.tomee.catalina.GlobalListenerSupport.lifecycleEvent(GlobalListenerSupport.java:130)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5378)
- locked <0x00000000e1115938> (a org.apache.catalina.core.StandardContext)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
- locked <0x00000000e1115938> (a org.apache.catalina.core.StandardContext)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1083)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1880)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- <0x00000000fb344d08> (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync)
- <0x00000000e0bca828> (a java.util.concurrent.ThreadPoolExecutor$Worker)
当 public void reproduce()
被 @PostConstruct
注释调用时,它们会死锁。
当它被另一个 bean 调用时,youCantGetMe
执行 return。
例如,以下设置有效:
@Startup
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DeadlockReproducer {
private final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, this.getClass());
@EJB
private DeadlockReproducerAid deadlockReproducerAid;
//@PostConstruct - no postconstruct now
public void reproduce(){
LOGGER.info("reproduce");
deadlockReproducerAid.lockMe();
}
public void youCantGetMe(){
LOGGER.info("youCantGetMe");
}
}
@Startup
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class DeadlockReproducerAid {
private final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, this.getClass());
@EJB
DeadlockReproducer deadlockReproducer;
public void lockMe(){
LOGGER.info("lockMe");
deadlockReproducer.youCantGetMe();
}
}
@Startup
@Singleton
public class DeadlockInvoker {
@EJB
DeadlockReproducer deadlockReproducer;
@PostConstruct
public void startup(){
deadlockReproducer.reproduce();
}
}
为什么会这样,我怎样才能在不借助外部调用程序的情况下使它工作?
编辑:
我开始发现这种行为与 EJB 中的单例生命周期有关。
单例在 @PostConstruct
完成 运行 之前不会进入 Ready
状态,并且可能当它的状态不是 Ready
时,它不会响应外部方法调用。
您需要标记您的第一个 ejb 需要第二个在它之前启动:https://docs.oracle.com/javaee/6/api/javax/ejb/DependsOn.html
除此之外,我没有发现代码有任何问题,单例使用可重入锁,所以这应该可以工作。
我猜这个行为与 EJB 中的单例生命周期有关。
我用第三个启动 bean 解决了这个问题,它依赖于两个单例,并在两个单例都已加载时手动调用其中一个单例的 start()
方法。为此,我添加了 start()
方法。
我本可以从 DeadlockReproducerAid
开始 DeadlockReproducer
,但这会掩盖第二个 class 的目的。