You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shiro.apache.org by "Mark Hale (JIRA)" <ji...@apache.org> on 2014/03/21 15:21:42 UTC

[jira] [Commented] (SHIRO-452) SimpleSession serialization failing

    [ 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)