[ 
https://issues.apache.org/jira/browse/SHIRO-452?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13943087#comment-13943087
 ] 

Mark Hale commented on SHIRO-452:
---------------------------------

I think I'm encountering a similar but slightly different problem. I have a 
single EhCache shared between two security manager webapp instances. When I 
login in one webapp, I sometimes receive:
{code}
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)
 ~[ehcache-2.8.1.jar:2.8.1]
        at 
net.sf.ehcache.store.disk.DiskStorageFactory.write(DiskStorageFactory.java:381) 
~[ehcache-2.8.1.jar:2.8.1]
        at 
net.sf.ehcache.store.disk.DiskStorageFactory$DiskWriteTask.call(DiskStorageFactory.java:473)
 ~[ehcache-2.8.1.jar:2.8.1]
        at 
net.sf.ehcache.store.disk.DiskStorageFactory$PersistentDiskWriteTask.call(DiskStorageFactory.java:1067)
 ~[ehcache-2.8.1.jar:2.8.1]
        at 
net.sf.ehcache.store.disk.DiskStorageFactory$PersistentDiskWriteTask.call(DiskStorageFactory.java:1051)
 ~[ehcache-2.8.1.jar:2.8.1]
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
~[na:1.7.0_25]
        at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
~[na:1.7.0_25]
        at 
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)
 ~[na:1.7.0_25]
        at 
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
 ~[na:1.7.0_25]
        at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
~[na:1.7.0_25]
        at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
~[na:1.7.0_25]
        at java.lang.Thread.run(Thread.java:724) ~[na:1.7.0_25]
Caused by: java.util.ConcurrentModificationException: null
        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:894) 
~[na:1.7.0_25]
        at java.util.HashMap$EntryIterator.next(HashMap.java:934) ~[na:1.7.0_25]
        at java.util.HashMap$EntryIterator.next(HashMap.java:932) ~[na:1.7.0_25]
        at java.util.HashMap.writeObject(HashMap.java:1098) ~[na:1.7.0_25]
        at sun.reflect.GeneratedMethodAccessor76.invoke(Unknown Source) ~[na:na]
        at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 ~[na:1.7.0_25]
        at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_25]
        at 
java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175) 
~[na:1.7.0_25]
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347) 
~[na:1.7.0_25]
        at 
org.apache.shiro.session.mgt.SimpleSession.writeObject(SimpleSession.java:461) 
~[shiro-core-1.2.3.jar:1.2.3]
        at sun.reflect.GeneratedMethodAccessor79.invoke(Unknown Source) ~[na:na]
        at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 ~[na:1.7.0_25]
        at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_25]
        at 
java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1541) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:439) 
~[na:1.7.0_25]
        at net.sf.ehcache.Element.writeObject(Element.java:867) 
~[ehcache-2.8.1.jar:2.8.1]
        at sun.reflect.GeneratedMethodAccessor78.invoke(Unknown Source) ~[na:na]
        at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 ~[na:1.7.0_25]
        at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_25]
        at 
java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429) 
~[na:1.7.0_25]
        at 
java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175) 
~[na:1.7.0_25]
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347) 
~[na:1.7.0_25]
        at 
net.sf.ehcache.util.MemoryEfficientByteArrayOutputStream.serialize(MemoryEfficientByteArrayOutputStream.java:97)
 ~[ehcache-2.8.1.jar:2.8.1]
        at 
net.sf.ehcache.store.disk.DiskStorageFactory.serializeElement(DiskStorageFactory.java:399)
 ~[ehcache-2.8.1.jar:2.8.1]
        ... 11 common frames omitted
{code}

I'm posting here because I think the solution to this jira will also solve my 
problem, which is also due to the disk writing thread being different to the 
servlet request thread. I believe to solve both problems, you need to modify 
SimpleSession.writeObject() so that it takes a copy of the attributes map 
before writing it (+ make fields volatile). Or alternatively, I guess the shiro 
Cache.put() implementation for EhCache could be modified to take a copy via 
clone() or something and pass that to EhCache instead of the original object.

> SimpleSession serialization failing
> -----------------------------------
>
>                 Key: SHIRO-452
>                 URL: https://issues.apache.org/jira/browse/SHIRO-452
>             Project: Shiro
>          Issue Type: Bug
>          Components: Caching , Session Management
>    Affects Versions: 1.2.1
>         Environment: Java 6 - EhCache 2.6.2
>            Reporter: Bruno GRIEDER
>
> We cache SimpleSession in EhCache which is configured with Overflow to Disk 
> and an LRU eviction policy.
> When the cache is full, EhCache will attempt to evict a session from the Disk 
> Storage to reclaim space.
> To evict the `SimpleSession`, EhCache will attempt to deserialize the 
> eveicted session first. From time to time, the deserialization of the 
> `SimpleSession` fails. When that happens the system is locked, since no 
> additional session can be created.
> `SimpleSession` has a custom serialization mechanism that calculates a bit 
> mask which indicates which fields of the `SimpleSession` contain values. This 
> bitMask is serialized first (as a Short) then the fields containing values.
> When deserialization is failing, the bitMask indicates that the `attributes` 
> Map contains data, however no `attributes` have actually been serialized and 
> the deserialization fails with a `java.io.OptionalDataException`.
> The discrepancy is very likely due to `attributes` being a non synchronized 
> Map: the SimpleSession is created on a Servlet thread, however the 
> serialization to Disk is performed by EhCache on one of its cache management 
> threads.
> SimpleSession fields should likely be marked as volatile and the Map should 
> be a Synchronized Map or SimpleSession should be made immutable.



--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to