You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Roger Forcada <ro...@gmail.com> on 2021/02/08 10:33:40 UTC
Issue in EventSubject->_registeredSubjects
First of all, since this is my first forum thread, I'd like to thank you for your excellent job in creating and maintaining Apache cayenne. It's a really good and practical piece of software. With the intention of making it better and helping as little as I can, I'd like to share with you an underlying issue we might have spotted.
We are seeing some ConcurrentModificationException, and after some examination we found out that the _registeredSubjects Map (WeakValueMap) in EventSubject class is static and not thread safe.
Every time a new context is created without SharedCacheEnabled (In the DataDomain), the EventSubject->getSubject method is called, and so it does some get/put in _registeredSubjects, which also consequently call ReferenceMap->checkReferenceQueue, which do a lot of non thread safe operations on the inner HashMap.
This could be a huge issue for highly concurrent applications.
For now, we are trying to make it work with a custom snapshot cache, which stores nothing, as we do not want to share or cache anything.
Please find the stack below:
StackTrace: 'java.util.ConcurrentModificationException
at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1526)
at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1524)
at org.apache.cayenne.util.ReferenceMap.checkReferenceQueue(ReferenceMap.java:242)
at org.apache.cayenne.util.ReferenceMap.get(ReferenceMap.java:138)
at org.apache.cayenne.util.WeakValueMap.get(WeakValueMap.java:33)
at org.apache.cayenne.event.EventSubject.getSubject(EventSubject.java:67)
at org.apache.cayenne.access.DataRowStore.createSubject(DataRowStore.java:97)
at org.apache.cayenne.access.DataRowStore.<init>(DataRowStore.java:91)
at org.apache.cayenne.access.DefaultDataRowStoreFactory.createDataRowStore(DefaultDataRowStoreFactory.java:54)
at org.apache.cayenne.configuration.server.DataContextFactory.createdFromDataDomain(DataContextFactory.java:115)
at org.apache.cayenne.configuration.server.DataContextFactory.createContext(DataContextFactory.java:61)
at org.apache.cayenne.configuration.CayenneRuntime.newContext(CayenneRuntime.java:124)
Thanks,
best,
Re: Issue in EventSubject->_registeredSubjects
Posted by Nikita Timofeev <nt...@objectstyle.com>.
Hi Roger,
Thank you for such a detailed report!
Here is an issue to track:
https://issues.apache.org/jira/browse/CAY-2698
On Mon, Feb 8, 2021 at 1:41 PM Roger Forcada <ro...@gmail.com> wrote:
>
> First of all, since this is my first forum thread, I'd like to thank you for your excellent job in creating and maintaining Apache cayenne. It's a really good and practical piece of software. With the intention of making it better and helping as little as I can, I'd like to share with you an underlying issue we might have spotted.
>
> We are seeing some ConcurrentModificationException, and after some examination we found out that the _registeredSubjects Map (WeakValueMap) in EventSubject class is static and not thread safe.
>
> Every time a new context is created without SharedCacheEnabled (In the DataDomain), the EventSubject->getSubject method is called, and so it does some get/put in _registeredSubjects, which also consequently call ReferenceMap->checkReferenceQueue, which do a lot of non thread safe operations on the inner HashMap.
>
> This could be a huge issue for highly concurrent applications.
>
> For now, we are trying to make it work with a custom snapshot cache, which stores nothing, as we do not want to share or cache anything.
>
> Please find the stack below:
>
> StackTrace: 'java.util.ConcurrentModificationException
> at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
> at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1526)
> at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1524)
> at org.apache.cayenne.util.ReferenceMap.checkReferenceQueue(ReferenceMap.java:242)
> at org.apache.cayenne.util.ReferenceMap.get(ReferenceMap.java:138)
> at org.apache.cayenne.util.WeakValueMap.get(WeakValueMap.java:33)
> at org.apache.cayenne.event.EventSubject.getSubject(EventSubject.java:67)
> at org.apache.cayenne.access.DataRowStore.createSubject(DataRowStore.java:97)
> at org.apache.cayenne.access.DataRowStore.<init>(DataRowStore.java:91)
> at org.apache.cayenne.access.DefaultDataRowStoreFactory.createDataRowStore(DefaultDataRowStoreFactory.java:54)
> at org.apache.cayenne.configuration.server.DataContextFactory.createdFromDataDomain(DataContextFactory.java:115)
> at org.apache.cayenne.configuration.server.DataContextFactory.createContext(DataContextFactory.java:61)
> at org.apache.cayenne.configuration.CayenneRuntime.newContext(CayenneRuntime.java:124)
>
>
> Thanks,
>
> best,
>
--
Best regards,
Nikita Timofeev