序列化循环对象树 – StackOverflowError – 需要自定义序列化代码

我正在制作一个Android应用程序,我有一个双向循环对象树,我需要序列化以填充Sqlite数据库中的blob字段。 但是默认的序列化实现会向我抛出StackOverflowError(底部的堆栈跟踪)。 但是我没有编写自定义java序列化代码的经验来避免这种情况。

我这个线程( 在Java中序列化对象时的StackOverflowError )他谈到了这个问题,但是在我的情况下如何实现它我真的不知道:

可以为这样的列表类定义一个writeObject()方法,当第一个链接被序列化时,只需遍历列表并迭代地序列化每个链接; 这将阻止使用默认的递归机制。

这是我的对象模型(看1 / M,而不是其他标志): 在此处输入图像描述

这是我用来将对象模型序列化为字节数组的方法(正确的不那么重要):

public byte[] serialize(Object object) { byte[] buf = null; try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos); out.writeObject(object); out.close(); buf = bos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return buf; } 

自定义序列化function:

 private void writeObject(java.io.ObjectOutputStream out) throws IOException { //please help me with this code } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { //please help me with this code } 

希望有人帮我解决这个问题。 任何线索都表示赞赏。

exception堆栈跟踪:

 05-25 20:28:16.231: E/AndroidRuntime(14451): FATAL EXCEPTION: main 05-25 20:28:16.231: E/AndroidRuntime(14451): java.lang.StackOverflowError 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.util.IdentityHashMap.findIndex(IdentityHashMap.java:419) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.util.IdentityHashMap.get(IdentityHashMap.java:371) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.dumpCycle(ObjectOutputStream.java:471) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1739) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.util.ArrayList.writeObject(ArrayList.java:651) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.lang.reflect.Method.invokeNative(Native Method) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.lang.reflect.Method.invoke(Method.java:507) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.util.ArrayList.writeObject(ArrayList.java:651) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.lang.reflect.Method.invokeNative(Native Method) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.lang.reflect.Method.invoke(Method.java:507) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575) 05-25 20:28:16.231: E/AndroidRuntime(14451): at java.io.ObjectOutputStream.writeObject 

Java序列化正确处理循环图,但长列表是一个问题。

如果我理解正确,你的问题与你链接的文章中的问题有点不同,因为该文章谈论的链接列表没有正确的writeObject ..当前你正在使用ArrayLists,它已经将对象存储为一个平面数组,并且也有一个合适的writeObject。

但是,如果我做对了,会发生什么或多或少:

你开始序列化对象A,在序列化期间遇到一个长列表,取第一个元素并序列化对象B,对象B也有一个长列表,它取第一个元素,再说它是A,因为它已经被序列化了跳过A,所以它不会以无限循环结束,然后转到B列表中的第二个对象,即C,C也有一个长列表,前两个元素又是A和B,所以它们是被跳过,第三个是D,它也有一个列表….和soooo。

由于这些步骤中的每一步都是堆栈中的几行,所以即使它们都是具有正确writeObject方法的ArrayLists,它也会填满。

如果这些列表与您的运行时相比,这些列表会扩展为相对“大”的数字,则可能就是这种情况。 这就是我在评论中提出的原因。 也许可以找到一种解决方案,避免序列化某些列表(使它们成为瞬态),并在“部分”反序列化后重建它们。