2012-05-25 5 views
2

Je fais une application android où j'ai un arbre objet cyclique bidirectionnel que je dois sérialisation pour remplir un champ blob dans une base de données SQLite. Mais l'implémentation de sérialisation par défaut renvoie une erreur StackOverflowError (pile trace en bas). Mais je n'ai aucune expérience dans l'écriture de code de sérialisation Java personnalisé pour éviter cette situation.arbre sérialisation objet cyclique - StackOverflowError - code sérialisation personnalisé nécessaire

I ce fil (StackOverflowError when serializing an object in Java) il parle de la question, mais la façon de le mettre en œuvre dans mon cas je n'ai pas vraiment une idée:

Il est possible de définir une méthode writeObject() pour une telle liste de classes qui, lorsque le premier lien est sérialisé, parcourt simplement la liste et sérialise chaque liaison de manière itérative; Cela empêchera l'utilisation du mécanisme récursif par défaut.

Ceci est mon modèle d'objet (regardez le 1/M, et non les autres signes): enter image description here

C'est la méthode que j'utilise pour sérialiser le modèle d'objet à un tableau d'octets (correctement pas importants):

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; 
    } 

fonctions de sérialisation personnalisées:

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 
} 

J'espère que quelqu'un m'aidera à résoudre ce problème. Toute idée est appréciée.

Exception trace de la pile:

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 
+0

Combien de tours, de joueurs, de parties et de places y a-t-il dans chaque blob sérialisé? J'ai une idée de ce qui se passe mais je voudrais le vérifier avec des chiffres :) –

+0

Tours: x, joueurs: 4-7, a joué: x * joueurs, sièges: 4-7. Chaque chose dans un blob - sérialisation de l'objet de jeu. –

+0

x est dans les dizaines, centaines, milliers: D –

Répondre

1

sérialisation Java gère correctement graphiques cycliques, mais les listes longues sont un problème. Si je comprends bien, votre problème est un peu différent de celui de l'article que vous avez lié, parce que cet article parle de listes chaînées sans writeObject correct ... alors que vous utilisez actuellement ArrayLists, qui stocke déjà des objets en tant que tableau plat, et ont aussi un writeObject approprié.

Cependant, si je me trompe pas, ce qui se passe plus ou moins ceci:

Vous commencez sérialisation objet A, au cours de cette sérialisation rencontre une longue liste, prend le premier élément et objet sérialise B, objet B a aussi une longue liste, il prend le premier élément, disons A à nouveau, puisqu'il est déjà sérialisé il saute A, donc il ne finit pas dans une boucle sans fin, mais va ensuite au deuxième objet dans la liste de B , qui est C, aussi C a une longue liste, les deux premiers éléments sont A et B à nouveau, donc ils sont ignorés, le troisième est D, qui a aussi une liste .... et soooo sur.

Étant donné que chacune de ces étapes comporte quelques lignes dans la pile, elle se remplit, même si elles sont toutes ArrayLists avec une méthode writeObject appropriée.

Cela peut être le cas si ces listes sont mises à l'échelle en nombres relativement "grands", par rapport à votre temps d'exécution. C'est pourquoi j'ai demandé dans le commentaire. Peut-être qu'une solution peut-être trouvée en évitant de sérialiser certaines listes (les rendant transitoires), et en les reconstruisant après la désérialisation "partielle".

+0

Je pense que vous avez raison .. Mais je ne peux pas vraiment comprendre comment reconstruire la liste. Comment feriez-vous cela? –

+0

J'ai réussi à le résoudre comme vous l'avez dit - Merci. J'ai fait la liste des Playeds du joueur transitoire et créé une fonction enrichModel et l'appeler après désérialisation le modèle: 'pour (round Round: game.Rounds) { \t \t \t pour (Played joué: round.Playeds) { \t \t \t \t joué.Joueur.Playeds.add (joué); \t \t \t} \t \t} ' –