-
Couldn't load subscription status.
- Fork 38.8k
Description
Richard Costine opened SPR-13493 and commented
This error is now happening sporadically during our acceptance tests. It looks to be caused by an internal list of strings (in spring's DefaultListableBeanFactory) which is updated via another thread, while an Iterator (backed by that same list of strings) is cycling over it.
If something is added (or deleted) to (or from) a collection while the collection is being iterated over, a ConcurrentModificationException will occur inside the next().
We have recently upgraded from Spring 3.1 to 4.1.6. With both Spring releases, we are using Akka and running in an OSGI container. When actors are instantiated, a spring createBean is done. That is where this sporadic exception now occurs.
39:15 ERROR [ akka.actor.OneForOneStrategy] - exception during creation
akka.actor.ActorInitializationException: exception during creation
at akka.actor.ActorInitializationException$.apply(Actor.scala:166) ~[com.typesafe.akka.actor_2.3.11.jar:na]
at akka.actor.ActorCell.create(ActorCell.scala:596) ~[com.typesafe.akka.actor_2.3.11.jar:na]
at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:456) ~[com.typesafe.akka.actor_2.3.11.jar:na]
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:478) ~[com.typesafe.akka.actor_2.3.11.jar:na]
at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:263) ~[com.typesafe.akka.actor_2.3.11.jar:na]
at akka.dispatch.Mailbox.run(Mailbox.scala:219) ~[com.typesafe.akka.actor_2.3.11.jar:na]
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397) [com.typesafe.akka.actor_2.3.11.jar:na]
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [org.scala-lang.scala-library_2.11.6.v20150224-172222-092690e7bf.jar:na]
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [org.scala-lang.scala-library_2.11.6.v20150224-172222-092690e7bf.jar:na]
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [org.scala-lang.scala-library_2.11.6.v20150224-172222-092690e7bf.jar:na]
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [org.scala-lang.scala-library_2.11.6.v20150224-172222-092690e7bf.jar:na]
+*Caused by: java.util.ConcurrentModificationException: null
at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:711) ~[na:1.8.0_31]
at java.util.LinkedHashMap$LinkedKeyIterator.next(LinkedHashMap.java:734) ~[na:1.8.0_31]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:471) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]*+
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:412) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors(BeanFactoryUtils.java:186) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1105) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1139) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1042) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:342) ~[org.apache.servicemix.bundles.spring-beans_4.1.6.RELEASE_1.jar:na]
at com.ccadllc.firebird.core.actors.SpringInjector.apply(Injector.scala:102) ~[com.ccadllc.firebird.core.actors_6.0.0.20150820212456.jar:na]
at com.ccadllc.firebird.core.actors.Injected$$anonfun$apply$2.apply(Injector.scala:45) ~[com.ccadllc.firebird.core.actors_6.0.0.20150820212456.jar:na]
at com.ccadllc.firebird.core.actors.Injected$$anonfun$apply$2.apply(Injector.scala:45) ~[com.ccadllc.firebird.core.actors_6.0.0.20150820212456.jar:na]
at akka.actor.TypedCreatorFunctionConsumer.produce(Props.scala:343) ~[com.typesafe.akka.actor_2.3.11.jar:na]
at akka.actor.Props.newActor(Props.scala:252) ~[com.typesafe.akka.actor_2.3.11.jar:na]
at akka.actor.ActorCell.newActor(ActorCell.scala:552) ~[com.typesafe.akka.actor_2.3.11.jar:na]
at akka.actor.ActorCell.create(ActorCell.scala:578) ~[com.typesafe.akka.actor_2.3.11.jar:na]
... 9 common frames omitted
There is a similar issue here:
The ConcurrentModificationException issue didn't occur with 3.1 because a copy of the underlying list was Iterated over, not the original list. It looks like this was changed for performance reasons, but now it is causing our application to fail sporadically. I looked at code for the 4.2.1 release and the lists are still not accessed in a threadsafe manner.
If there are no plans to fix this code to ensure that the lists are accessed in a synchronized fashion (using a CopyOnWriteArrayList, or by giving the option for the lists to be copied before attempting to Iterate over them, or perhaps synchronizing on the lists around the iteration) is there any way for us to tell the context to use our own custom bean factory that does this? We are willing to sacrifice some performance degradation, in order to allow the application to still function similar to the way it was working under the old 3.1 release.
Currently we are synchronizing around the createBean, and for some cases it seems to fix the problem. However, this is a very large application and we feel the best way to ensure that it is fixed everywhere is to ensure that the beanFactory itself can handle access by multiple threads.
Affects: 4.1.6
Issue Links:
- Registering two beans at the same time throws ConcurrentModificationException [SPR-12503] #17108 Registering two beans at the same time throws ConcurrentModificationException
- ConcurrentModificationException thrown while iterating over bean definition names in DefaultListableBeanFactory#getBeansWithAnnotation(Class<? extends Annotation> annotationType) [SPR-12688] #17286 ConcurrentModificationException thrown while iterating over bean definition names in DefaultListableBeanFactory#getBeansWithAnnotation(Class<? extends Annotation> annotationType)
- ConcurrentModificationException in DefaultListableBeanFactory.doGetBeanNamesForType() [SPR-13123] #17714 ConcurrentModificationException in DefaultListableBeanFactory.doGetBeanNamesForType()
- Doc: DefaultListableBeanFactory is not thread-safe for manual singleton registration [SPR-12970] #17562 Doc: DefaultListableBeanFactory is not thread-safe for manual singleton registration
- DefaultListableBeanFactory should allow efficient access to current bean names [SPR-12404] #17012 DefaultListableBeanFactory should allow efficient access to current bean names
Referenced from: commits 097bcfb
1 votes, 4 watchers