You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
a) I have only seen once, so cannot reproduce
b) I'm quite sure is caused by an @Autowired setter called with a null argument (which should be impossible)
When analyzing the problem, we found that three instances of the bean being autowired were instantiated in rapid succession (i.e. concurrently). This made us think of checking whether there maybe concurrency issues within Springs bean initialization code. Ultimately I looked at the code in AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement.inject() and I think I came up with a race condition scenario that does explain the injected null reference:
Let's say there are 3 Threads: t1, t2, t3 and the AutowiredMethodElement is in the state cached == false, cachedMethodArguments == null. This means that there probably hasn't been any call to inject() before and checking our log files, we indeed found that we didn't instantiate a bean of this type before. Now what I guess could have happened is:
t1 enters, finds cached == false, steps into else block and is interrupted
t2 enters, finds cached == false, steps into else block and is interrupted
t1 continues, fills in cachedMethodArguments, sets cached = true
t3 enters, finds cached == true, steps into if block and is interrupted
t2 continues, executes cachedMethodArguments = new Object[...] and is interrupted (chachedMethodArguments contains null references now!)
t3 continues, copies cachedMethodArguments[i] to arguments[i] (all null)
t3 invokes @Autowired annotated method, thereby injecting the null value
Have I missed any synchronization mechanism that prevents this? If not, it's probably a bug that needs fixing ;-)
Thanks for raising this! There is indeed a potential race condition there... I've revised this with a synchronized block for the non-cached case, which should hopefully be a good tradeoff between efficient access and properly coordinated caching. This will be available in the upcoming 3.0 M3 release.
Mattias Nissler opened SPR-5658 and commented
At work, we've hit a bug in an application that:
a) I have only seen once, so cannot reproduce
b) I'm quite sure is caused by an
@Autowired
setter called with a null argument (which should be impossible)When analyzing the problem, we found that three instances of the bean being autowired were instantiated in rapid succession (i.e. concurrently). This made us think of checking whether there maybe concurrency issues within Springs bean initialization code. Ultimately I looked at the code in AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement.inject() and I think I came up with a race condition scenario that does explain the injected null reference:
Consider AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement.inject():
Let's say there are 3 Threads: t1, t2, t3 and the AutowiredMethodElement is in the state cached == false, cachedMethodArguments == null. This means that there probably hasn't been any call to inject() before and checking our log files, we indeed found that we didn't instantiate a bean of this type before. Now what I guess could have happened is:
@Autowired
annotated method, thereby injecting the null valueHave I missed any synchronization mechanism that prevents this? If not, it's probably a bug that needs fixing ;-)
Affects: 2.5.6
Referenced from: commits a2fdb68
The text was updated successfully, but these errors were encountered: