2

Sqlite データベースの blob フィールドに入力するためにシリアル化する必要がある双方向循環オブジェクト ツリーがある Android アプリを作成しています。しかし、デフォルトのシリアライゼーションの実装では、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;
    }

カスタムのシリアル化関数:

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
}

誰かがこの問題を解決するのを手伝ってくれることを願っています. 手がかりをいただければ幸いです。

例外スタック トレース:

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
4

1 に答える 1

1

Java シリアライゼーションは循環グラフを正しく処理しますが、長いリストは問題です。

私が正しく理解している場合、あなたの問題は、リンクした記事の問題とは少し異なります。その記事では、適切な writeObject のないリンクされたリストについて話しているためです..現在、オブジェクトをフラット配列として既に格納している ArrayLists を使用しています。適切な writeObject もあります。

ただし、私が正しく理解した場合、何が起こるかは多かれ少なかれ次のとおりです。

オブジェクトAのシリアル化を開始すると、そのシリアル化中に長いリストに遭遇し、最初の要素を取得してオブジェクトBをシリアル化し、オブジェクトBにも長いリストがあり、最初の要素を取得します。これは、すでにシリアル化されているため、再びAです。 A をスキップするため、無限ループにはなりませんが、B のリストの 2 番目のオブジェクトである C に移動します。また、C には長いリストがあり、最初の 2 つの要素は再び A と B であるため、それらははスキップされ、3 番目は D で、これにもリストがあります。

これらの各ステップは、スタック ステージ内の数行であるため、適切な writeObject メソッドを使用したすべての ArrayList であっても、いっぱいになります。

これは、使用しているランタイムと比較して、これらのリストが比較的「大きな」数にスケーリングされる場合に当てはまります。ということでコメントで質問させていただきました。おそらく、いくつかのリストをシリアル化する (それらを一時的にする) ことを避け、「部分的な」逆シリアル化の後にそれらを再構築することで解決策が見つかるかもしれません。

于 2012-05-25T19:41:17.087 に答える