Initialization blocked by multi-threaded event publishing [SPR-16357] #20904
Description
Mark Paluch opened SPR-16357 and commented
Publishing events can block the container initialization in conjunction with event publishing from a different thread.
This can happen if events are published from a bean constructor while its bean is instantiated and events get published in a different thread while the constructed bean awaits completion of event publishing.
Consider following code:
@Component
class Foo {
Foo(ApplicationEventPublisher publisher) throws Exception {
Thread t = new Thread(() -> publisher.publishEvent(new Object()));
t.start();
t.join();
}
}
The code above publishes an event in an other thread than the constructing thread while awaiting completion before the constructor progresses.
It leads to a thread state like:
"Thread-19@5373" daemon prio=5 tid=0x22 nid=NA waiting for monitor entry
java.lang.Thread.State: BLOCKED
waiting for main@1315 to release lock on <0x17bd> (a java.util.concurrent.ConcurrentHashMap)
at org.springframework.context.event.AbstractApplicationEventMulticaster.getApplicationListeners(AbstractApplicationEventMulticaster.java:189)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:133)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:399)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:353)
at com.example.demo.Foo$1.run()
"main@1315" prio=5 tid=0xf nid=NA waiting (Thread calling initialization code)
java.lang.Thread.State: WAITING
blocks Thread-19@5373
at java.lang.Object.wait(Object.java:-1)
at java.lang.Thread.join(Thread.java:1252)
at java.lang.Thread.join(Thread.java:1326)
at com.example.demo.Foo.<init>
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeConstructorAccessorImpl.java:-1)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:271)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1270)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$87.1534495070.getObject(Unknown Source:-1)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
- locked <0x17bd> (a java.util.concurrent.ConcurrentHashMap)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:758)
The example originates from reactive code in which a constructor is used to call initialization code using .block()
for synchronization, see DATAMONGO-1841.
Affects: 5.0 GA
Issue Links:
- DATAMONGO-1841 Reactive mongodb hangs on block() when used in component initialization
- Asynchronous initialization of beans during startup [SPR-14920] #19487 Asynchronous initialization of beans during startup
- Parallel bean initialization during startup [SPR-8767] #13410 Parallel bean initialization during startup
0 votes, 8 watchers