当我对包装类进行序列化然后反序列化map.subMap时,我将遇到OptionalDataException。
似乎OptionalDataException与基元有关,但是在映射中,我总是将对象装箱的基元正确。那么我该如何解决呢?
编辑:添加了同步块
public class SerializeableSubMap<K, V> implements NavigableMap<K, V>, Serializable {
private static final long serialVersionUID = -7002458872266068959L;
private NavigableMap<K, V> map;
public SerializeableSubMap(NavigableMap<K, V> map) {
this.map = map;
}
private void writeObject(ObjectOutputStream stream) throws IOException {
synchronized (map) {
stream.writeInt(map.size());
Iterator<Entry<K, V>> itr = map.entrySet().iterator();
Entry<K, V> next;
while (itr.hasNext()) {
next = itr.next();
stream.writeObject(next.getKey());
stream.writeObject(next.getValue());
}
}
//stream.close();
}
private void readObject(ObjectInputStream stream) throws IOException {
int size = stream.readInt();
map = new ConcurrentSkipListMap<K, V>();
for(int i = 0; i < size; i++) {
try {
// get OptionalDataException here!
map.put((K) stream.readObject(), (V) stream.readObject());
} catch (Exception e) {
throw new IOException(e);
}
}
}
// delegate map interface methods to map object
}
编辑2:
private void writeObject(ObjectOutputStream stream) throws IOException {
synchronized (map) {
int s = map.size();
stream.writeInt(map.size());
Iterator<Entry<K, V>> itr = map.entrySet().iterator();
Entry<K, V> next;
int i=0;
while (itr.hasNext()) {
next = itr.next();
stream.writeObject(next.getKey());
stream.writeObject(next.getValue());
i++;
}
if (s != i) {
throw new ConcurrentModificationException();
}
}
//stream.close();
}
最佳答案
我能想到的原因之一是对地图的并发修改。假设执行以下语句后执行删除操作,会发生什么情况?
stream.writeInt(map.size());
最初说的是,当检索到地图大小时,地图中存在的元素数为2,但是说其他线程同时删除了地图中的一个元素,因此现在地图中存在的元素数为1。被写入流中的只有一对键值对(2个对象)。
但是有趣的是,在读取大小时读取的是2个键值对(4个对象),因为我们将大小读取为2,所以即使写入的只是一个键值对,我们也会尝试消耗2个键值对。
这是我们与该领域许多客户一起经历的。后来,所有这些都变成了并发修改问题。所以我建议您检查一下。
entrySet的Javadoc不会确认任何修改都会引发并发修改异常。
Set> entrySet()
返回此映射中包含的映射的Set视图。该集合由地图支持,因此对地图的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射(通过迭代器自己的remove操作或通过迭代器返回的映射条目上的setValue操作除外),则迭代的结果不确定。该集合支持元素删除,该元素通过Iterator.remove,Set.remove,removeAll,retainAll和clear操作从映射中删除相应的映射。它不支持add或addAll操作。
关于java - 自定义(de-)序列化方法抛出java.io.OptionalDataException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30707374/