-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Description
Jon Seymour opened SPR-7635 and commented
There remains a thread safety issue in AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement
This issue is unrelated to the issue reported in #10329 and represents a seperate exposure.
The issue was detected with Spring 2.5.6. Inspection reveals that the same issue exists in Spring 3.0.4.RELEASE
In the description that follows, Block A refers to the code starting at line 535 of org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
and Block B refers to the code start at line 593 of the same class.
Both lines are within the inject(Object bean, String beanName, PropertyValues pvs) method of the AutowiredMethodElement inner class.
The blocks are quoted here for ease of reference:
// Block A - line 535
if (this.skip == null && this.pd != null && pvs != null && pvs.contains(this.pd.getName())) {
// Explicit value provided as part of the bean definition.
this.skip = Boolean.TRUE; Line 535
}
// Block B - line 593
if (this.skip == null) {
if (this.pd != null && pvs instanceof MutablePropertyValues) {
((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName()); // Line 595
}
this.skip = Boolean.FALSE; // Line 597
}
The issue arises because the statements execute in Block A and Block B are not executed atomically. In particular, if a Thread 1 is suspended after Line 595 by the Java Scheduler, then pvs.contains(this.pd.getName()) will return true for some other thread, Thread 2, executing block A causing Thread 2 to take the branch in that block.
If Thread 2 is then suspended before reaching Line 535 and Thread 1 executes line 597 then thread 2 is resumed, this.skip will be set to TRUE and remain TRUE.
As a result all further executions of the inject method will fail to execute the body of the inject method resulting in the failure of Spring to inject autowired dependencies into all subsequent instances of the bean until such time as the bean factory is eventually refreshed. On the otherhand, if thread 1 executes to completion without being interleaved with Thread 2, this.skip will be set to false and the intended behaviour will be observed.
The issues can occur even without the specified thread interleavings, given Java Memory Model implementation considerations.
Affects: 2.5.6, 3.0.4
Issue Links:
- NullPointerException in InjectionMetadata [SPR-7686] #12342 NullPointerException in InjectionMetadata
- Thread safety issue in InjectionMetaData affecting setter methods annotated with @Resource tags [SPR-7642] #12298 Thread safety issue in InjectionMetaData affecting setter methods annotated with
@Resource
tags