Java 如何处理序列化大对象时发生的StackOverflower错误?

Java 如何处理序列化大对象时发生的StackOverflower错误?,java,serialization,stack-overflow,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.clos

以下是我的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)时,我得到了错误StackOverflowerError。我的问题是:在我在内存中构建对象之后,为什么会发生此错误

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

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;
}
然后我有两个问题:

  • out.writeObject(临时);因为temp有一个对下一个节点的引用,所以当我写temp时,递归调用也会发生。即使我用defaultWriteObject覆盖PostNode的writeObject方法,同样的情况也会继续。我说得对吗?如果是这样,我可以做些什么来避免这种递归调用
  • 如何覆盖readObject()方法
      如果看不到正在序列化的类,就很难知道,但我猜对象图太复杂了。Java的默认序列化机制通过对象图递归工作;也就是说,如果对象A引用了B,并且序列化了A,那么它必须走到B并序列化它。如果B然后引用C,C引用D,依此类推,那么递归算法可能必须深入到导致堆栈溢出的程度


      如果这就是导致问题的原因,您应该编写自己的
      readObject
      writeObject
      ,尽可能避免这种递归构建。

      如果您有一个深度嵌套的对象结构,则需要一个深度堆栈来遍历。您应该在异常堆栈跟踪中看到这一点
      ObjectOutputStream
      ObjectInputStream
      在堆栈空间方面并不特别节省

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

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


      递归问题来自PostNode类,而不是PostList类,您实际上还没有对此做任何事情。您需要一个显式遍历列表的PostNode.writeObject()、一个对称的readObject()方法和一个临时的“next”字段。

      如果不知道索引是什么,很难说。可能重复:这也可以帮助你:我想我的问题是,根据你的建议,索引的帖子列表是一个长链表。谢谢你的帮助@ASSYLASIS我尝试根据您的建议覆盖方法
      readObject
      writeObject
      ,我遇到了上面显示的新问题。你能告诉我如何覆盖这两种方法,或者给我网上的资源吗?我从中发现了一些东西,但我认为我的问题更复杂@Tom Hawtin-TackLine但是设置
      next
      字段瞬态意味着下一个字段将不会被序列化。如果是这样,当我反序列化一个post节点时,我如何知道下一个节点是谁@EJP@jerry_sjtu它将由循环序列化。事实上,您当前的代码对列表进行了两次序列化:一次是因为非瞬态的“next”字段,另一次是因为lop,它位于错误的类中。Yur反序列化循环应将下一个字段设置为流中的下一个对象,如果为null,则中断。
      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();
          }
      }