序列化一个大对象时如何处理StackOverflowError?

时间:2012-03-16 12:58:54

标签: java serialization stack-overflow

这是我的java代码:

    FileOutputStream fos = null; 
    ObjectOutputStream out = null;
    try {
        fos = new FileOutputStream(pathName);
        out = new ObjectOutputStream(fos);
        out.writeObject(index);
        out.close();
        fos.close();
    } catch (IOException e) {
        LogManager.writeLogToFile(e.getMessage());
        e.printStackTrace();
    }

索引是我自己的反向文档索引的实例。我已经在内存中构建了对象索引,但是当我将它传递给方法writeObject(index)时,我得到错误StackOverflowError。我的问题是:为什么在我在内存中构建了对象后发生了这个错误?

假设索引的数据结构如下:

class InvertedIndex{
    private HashMap<String, PostList> index;
}
class PostList{
    private int size;
    private PostNode first;
}
class PostNode{
    private String key;
    private double weight;
    private PostNode next;
}

为了避免递归调用,我覆盖了PostList的writeObject和readObject方法,因为它可能是一个很长的列表:

class PostList{
     private void writeObject(ObjectOutputStream out) throws IOException{
            PostNode temp = first;
            while(temp != null){
                  out.writeObject(temp);
                  temp = temp.getNext();
            }
     }
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
            in.defaultReadObject();
    }
}

然后我得到两个问题:

  • out.writeObject(临时);因为temp有对下一个节点的引用,所以当我写te​​mp时,也会发生递归调用。即使我用defaultWriteObject覆盖PostNode的writeObject方法,相同的情况也会继续。我对吗?如果是这样,我该怎么做才能避免这种递归调用?
  • 如何覆盖readObject()方法?

3 个答案:

答案 0 :(得分:1)

如果没有看到你正在序列化的课程,很难知道,但我的猜测是对象图太复杂了。 Java的默认序列化机制通过对象图递归地工作;也就是说,如果你有一个带有对B的引用的对象A,并且你序列化了A,那么它必须走到B并序列化它。如果B然后引用C,并且C引用D,依此类推,那么递归算法可能必须深入到导致堆栈溢出。

如果这是造成问题的原因,您应该编写自己的readObjectwriteObject,以避免这种递归构建,如果可能的话。

答案 1 :(得分:0)

如果你有一个深层嵌套的对象结构,那么需要一个深层栈来遍历。你应该在异常堆栈跟踪中看到这一点。堆栈空间ObjectOutputStreamObjectInputStream并不是特别节俭。

如果您尝试序列化链接列表之类的内容,那么最好实现迭代列表而不是递归的readObjectwriteObject方法。

答案 2 :(得分:0)

您的readObject()方法与您的writeObject()方法不匹配,因此它可能根本不起作用,并且您的writeObject()方法不会向默认序列化添加任何值。如果没有两者,你会更好。

递归问题来自PostNode类,而不是PostList类,你还没有真正做过任何事情。你需要一个明确遍历列表的PostNode.writeObject(),一个对称的readObject()方法和一个瞬态'next'字段。