在ehcache中序列化元素时出错

时间:2016-03-05 16:12:01

标签: java serialization replication ehcache

在ehcache中放置一个元素时出现以下错误。有谁知道为什么会出现这个错误?

提前谢谢。

这是放方法:

  @SuppressWarnings("unchecked")
  @Override
  public void putActivity(Activity activity) {
    // put activity itself
    Serializable activityKey = KEY_PREFIX_ACTIVITY + activity.getId();
    final Element activityElement = new Element(activityKey, activity);
    getCache().put(activityElement);

    // add activity to the list of user
    ArrayList<Activity> activities = null;
    Serializable userKey = KEY_PREFIX_USER_ACTIVITIES + activity.getExecutingUserId();
    Element userActivities = getCache().get(userKey);
    if (userActivities == null) {
      activities = new ArrayList<Activity>();
      userActivities = new Element(userKey, activities);
    } else {
      activities = (ArrayList<Activity>) userActivities.getObjectValue();
    }
    activities.add(activity);
    getCache().put(userActivities);
  }

这是相应的erorr:

Mrz 05, 2016 11:07:40 AM net.sf.ehcache.store.disk.DiskStorageFactory$DiskWriteTask call
Schwerwiegend: Disk Write of u-1 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:405)
    at net.sf.ehcache.store.disk.DiskStorageFactory.write(DiskStorageFactory.java:385)
    at net.sf.ehcache.store.disk.DiskStorageFactory$DiskWriteTask.call(DiskStorageFactory.java:477)
    at net.sf.ehcache.store.disk.DiskStorageFactory$PersistentDiskWriteTask.call(DiskStorageFactory.java:1071)
    at net.sf.ehcache.store.disk.DiskStorageFactory$PersistentDiskWriteTask.call(DiskStorageFactory.java:1055)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.util.ConcurrentModificationException
    at java.util.ArrayList.writeObject(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor33.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteObject(Unknown Source)
    at net.sf.ehcache.Element.writeObject(Element.java:875)
    at sun.reflect.GeneratedMethodAccessor31.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at net.sf.ehcache.util.MemoryEfficientByteArrayOutputStream.serialize(MemoryEfficientByteArrayOutputStream.java:97)
    at net.sf.ehcache.store.disk.DiskStorageFactory.serializeElement(DiskStorageFactory.java:403)
    ... 10 more

以及来自ehcache源代码的更多详细信息:

    private MemoryEfficientByteArrayOutputStream  [More ...] serializeElement(Element element) throws IOException {

         // A ConcurrentModificationException can occur because Java's serialization


         // mechanism is not threadsafe and POJOs are seldom implemented in a threadsafe way.


         // e.g. we are serializing an ArrayList field while another thread somewhere in the application is appending to it.


         try {



             return MemoryEfficientByteArrayOutputStream.serialize(element);



         } catch (ConcurrentModificationException e) {


             throw new 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", e);


         }



  }

2 个答案:

答案 0 :(得分:3)

您正在序列化对象时更新对象(ehcache尝试将其保存到磁盘)。您应该只在缓存中存储一​​个不可变对象。

在您的情况下,不要尝试重用ArrayList,创建一个新的:

if (userActivities == null) {
      activities = new ArrayList<Activity>();
      userActivities = new Element(userKey, activities);
} else {
      activities = new ArrayList<Activity>((List) userActivities.getObjectValue());
}

答案 1 :(得分:0)

您可以实例化 CopyOnWriteArrayList,而不是 ArrayList。