【问题标题】:StackOverflowError when i serialize an object当我序列化一个对象时出现 StackOverflowError
【发布时间】:2012-11-24 13:40:05
【问题描述】:

我想用这个方法序列化一个对象:

public void serializ(CRDT m) throws IOException {
    ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
    ObjectOutputStream stream = new ObjectOutputStream(byteOutput);
    stream.writeObject(m);
    sumMemory = byteOutput.size();

    stream.flush();
    stream.close();
    byteOutput.flush();
    byteOutput.close();
}

我有一个例外java.lang.StackOverflowError

Exception in thread "main" java.lang.StackOverflowError
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1169)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    ...

我阅读了一些论坛,我需要重新实现 writeObject / readObject 方法。 这是唯一可能的解决方案吗?以及如何重新实现writeObject / readObject

我要序列化的对象是: http://pastebin.com/D1kEidtn

导致错误的两个类是: pastebin.com/Sb3X0Quqenter link description here

【问题讨论】:

  • 如果您可以发布您想要序列化的对象的代码将会很有帮助。我建议使用 BufferedOutputStream。
  • 向我们展示myObject 类。
  • 由于CRDTabstract 我们还需要具体类的代码。
  • @Mehdi:如果您无法发布具体类的代码,那么您应该尝试将代码剥离到相关部分。当然,如果您能提供给我们一个SSCCE 的例子,那就最好不过了。
  • 只要打印出导致问题的对象的类,然后分析该类的代码。很有可能,您自己会发现问题。

标签: java serialization stack-overflow


【解决方案1】:

CRDT 是被序列化的 Object m 的超类。 错误是从 CRDT 派生的类似乎有对自身的引用,导致无限递归
您可以在堆栈跟踪中看到这一点。
Tipp 通过使用调试器或在您的 serialize() 方法的开头添加 System.out.println(m.getClass()) 找出对象 CRDT m: 的类。 然后当你知道类时,检查对象是否有对自身的引用。

【讨论】:

  • 无限递归也可能,而且我实际上认为是这种情况,是由一个大的链接数据结构引起的,这导致 java.io.ObjectOutputStream.defaultWriteFields 上的大递归。
  • @Herbert 我不这么认为,因为链接意味着引用,并且被引用的对象在序列化过程中保存在一个表中,以避免对象的重复输出。
  • 表的使用与递归的使用并不矛盾,因此也不与堆栈溢出的可能性相矛盾,事实上,这是一个非常常见的“错误”(我认为这是一个错误java,但有些人可能认为它是一个特性):ideone.com/wATlNK
  • @Herbert 可以实现序列化以避免无限循环。但这将是一个重大的放缓。您发布的有趣代码。这确实可以被视为一个错误。我个人不信任对象恢复机制,我用 id 替换了referecnes,并在反序列化后自己恢复它们。
  • @Herbert,但现在我明白你是对的,Exeption 很可能是由默认序列化引起的。我改变了我的答案
【解决方案2】:

您尚未发布具体课程,因此很难发现错误,但
简而言之,任何递归算法都可能溢出堆栈并且堆栈是有限的。
对于深度嵌套的对象图,Java 内置序列化需要过多的堆栈空间。
有关详细信息,请参阅
http://c2.com/cgi/wiki?JavaSerializationIsBroken
http://c2.com/cgi/wiki?JavaSerializationAndTheStack

【讨论】:

    【解决方案3】:

    我只是将-Xss512m 添加到 Netbeans,它的工作:D

    【讨论】:

      【解决方案4】:

      顺便说一句,我遇到了同样的问题,但看起来我的问题与检查点持续时间过长有关。看起来,Spark 在写出它时会维护某种对象链接,如果持续时间太大,它将导致堆栈溢出。

      【讨论】:

        猜你喜欢
        • 2010-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-02
        • 1970-01-01
        • 2011-09-18
        • 1970-01-01
        相关资源
        最近更新 更多