We have a web application that averages around 30 hits per minute. After upgrading Spring from 3.2.5 to 3.2.7 we observed some problems. Over a period of one week there was a slow increase in heap usage resulting in OutOfMemoryErrors, and a gradual increase in CPU per request by a factor of ten.
CPU profiling shows the bulk of the time increase is in the method adaptInnerBeanName of BeanDefinitionValueResolver. Heap analysis shows the increase in memory use is in the ConcurrentHashMaps dependentBeanMap and dependenciesForBeanMap of DefaultSingletonBeanRegistry.
This problem appears to be a result of commit d0fc38e, the fix for issue #15757.
This application uses something on the order of 100 or so prototype beans per request. Over time providing these beans with unique names is an unmanageable proposition.
Affects: 3.2.6, 3.2.7, 3.2.8
#15757 Dependency Injection issue when using ManagedMap or ManagedList in BeanDefinitionParser
#15871 Regression: InjectionMetadata cache needs to handle different bean classes per bean name
That fix for #15757 was only meant to guarantee a unique name per inner bean definition, in case there were several inner bean definitions used across a context. For a prototype bean definition, that check should only happen on first creation of a bean instance... The endless bean name generation that you're seeing is a bug in that algorithm, generating a name per bean instance instead of per bean definition :-(
We'll fix this for 4.0.3, also trying to make bean definition merging as efficient as possible for the inner bean prototype case. To be backported to 3.2.9 as well.
Restored original singleton-only adaptInnerBeanName behavior, avoiding endless unique name calculation for every single prototype instance. Non-named inner BeanDefinition objects now suffixed with an identity hex code analogous to non-named XML bean definitions, largely avoiding naming collisions to begin with. After #15871, post-processors can deal with unstable classes per bean name, so occasional collisions aren't a hard problem anymore.
We noticed this issue with Spring v3.2.8.RELEASE while load testing our web applications with unnamed prototype beans declared in XML.
Unnamed prototype beans declared by annotations are not affected because the AnnotationBeanNameGenerator uses the class name by default.
The injectionMetadataCache was indefinitely growing until we got OOMs, while it was using over 75% of the heap (> 500 MB per web app).
After applying commit 5c3f6a1 over v3.2.8.RELEASE, this issue is indeed resolved.
The injectionMetadataCache is currently a ConcurrentHashMap with no size limit and no cleanup strategy.
I'm guessing using a real cache such would prevent such issues.