I recently added Shiro with EH Cache to my webapp and since then I am seeing a few ConcurrentModificationException:
[shiro-active%0053ession%0043ache.data] ERROR net.sf.ehcache.store.disk.DiskStorageFactory - Disk Write of 3ae3f634-cd97-4614-bd04-517d81623971 failed:
net.sf.ehcache.CacheException: Failed to serialize element due to ConcurrentModificationException. This is frequently the result of inappropriately sharing thread unsafe object (eg. ArrayList, HashMap, etc) between threads
at net.sf.ehcache.store.disk.DiskStorageFactory.serializeElement(DiskStorageFactory.java:401)
at net.sf.ehcache.store.disk.DiskStorageFactory.write(DiskStorageFactory.java:381)
at net.sf.ehcache.store.disk.DiskStorageFactory$DiskWriteTask.call(DiskStorageFactory.java:473)
at net.sf.ehcache.store.disk.DiskStorageFactory$PersistentDiskWriteTask.call(DiskStorageFactory.java:1067)
at net.sf.ehcache.store.disk.DiskStorageFactory$PersistentDiskWriteTask.call(DiskStorageFactory.java:1051)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
The issue I have is that the stack trace is not giving much information about where the issue is in the code and as the webapp is pretty big.
Any tips on how to find and fix the error would be much appreciated.
EDIT: the problem seems to occur when the user goes from the ROOT module 'www.my-site.com/' to the app module 'www.my-site.com/app/'. Both modules are running Shiro on a different cache/session (i.e. no SSO yet) the only thing they share are 3 cookies: locale/currency/cookie-consent. I don't think it comes from the cookies as they are accessed at the beginning of the request (i.e. when leaving the ROOT to get to the app only the app accesses the cookies and saves the locale in the session).
Any idea of what might be causing the issue?
---------------EDIT -------- Here is a more detailed stack trace. Shiro's simple session seems to be playing a role:
Caused by: java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
at java.util.HashMap$EntryIterator.next(HashMap.java:847)
at java.util.HashMap$EntryIterator.next(HashMap.java:845)
at java.util.HashMap.writeObject(HashMap.java:1012)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:962)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at org.apache.shiro.session.mgt.SimpleSession.writeObject(SimpleSession.java:461)
-------------EDIT 2 ------------------
I think I found the origin of the problem. I have a method that stores a few String attributes in the session. The app works fine without it and the issue comes back as soon as I uncomment it. What I don't understand is why this is causing a concurrent modification exception: this method is only saving Strings in the session, and there is only one thread accessing the session. Any clues?
-----------EDIT 3 -------------------
I replaced the Strings by 4 POJOs. Now the exception only occur once when the user first lands on a page (right before starting executing the doGet(...) code.
This doesn't seem to create any working issues so I'll probably just ignore it for now. If anybody understands what's happening please give me a shout.