2009-01-13 18 views
10

Estoy escribiendo una aplicación en Java usando Swing. Estoy intentando implementar la funcionalidad para guardar y cargar estados de simulación en la simulación que estoy ejecutando. Toda la simulación se mantiene como un objeto desconectado de Swing. Estoy tratando de serializar mi clase de simulación con este código:StackOverflowError al serializar un objeto en Java

public void saveSimulationState(String simulationFile) { 
    try { 
     Serializable object = this.sm; 
     ObjectOutputStream objstream = new ObjectOutputStream(new FileOutputStream(simulationFile)); 
     objstream.writeObject(object); 
     objstream.close(); 
    } catch (IOException e) { 
     System.out.println(e.getMessage()); 
    } 
} 

pero me da el siguiente error (que es enorme).

Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError 
     at java.io.ObjectStreamClass.processQueue(ObjectStreamClass.java:2234) 
     at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:266) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1106) 
     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
     at java.util.ArrayList.writeObject(ArrayList.java:570) 
     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
     at java.util.ArrayList.writeObject(ArrayList.java:570) 
     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
     at java.util.ArrayList.writeObject(ArrayList.java:570) 
     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
     at java.util.ArrayList.writeObject(ArrayList.java:570) 
     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
     at java.util.ArrayList.writeObject(ArrayList.java:570) 
     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
     at java.util.ArrayList.writeObject(ArrayList.java:570) 
     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
     at java.util.ArrayList.writeObject(ArrayList.java:570) 
     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
     at java.util.ArrayList.writeObject(ArrayList.java:570) 
     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461) 

¿Alguien me puede decir qué está causando esta excepción?

+0

Ah, y todo mi código se pueden encontrar aquí: http://code.google.com/p/sensor-protocol-simulation/ El código de ejemplo se tomó de GraphPanel.java en la parte vista. – utdiscant

Respuesta

12

Interesante post de Chen:

When debugging a stack overflow, you want to focus on the repeating recursive part

En su caso:

 at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474) 
     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392) 
     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150) 
     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326) 
     at java.util.ArrayList.writeObject(ArrayList.java:570) 
     at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945) 
     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461) 

Si va a cazar a través de su base de datos de seguimiento de defectos tratando para ver si esto es un problema conocido o no, una búsqueda de las funciones superiores en la pila es poco probable para encontrar algo interesante. Eso es porque los desbordamientos de pila tienden a ocurrir en un punto aleatorio en la recursión; cada desbordamiento de pila se ve superficialmente diferente de todos los demás, incluso si son del mismo desbordamiento de pila.

Una vez que superas la confusión inicial, el seguimiento de la pila se establece en un bonito patrón repetitivo que consta de las mismas funciones x una y otra vez.
Identificar el inicio del patrón de repetición no es importante, porque el punto de partida será diferente para cada choque, de la misma manera que la nota precisa que excede su rango de canto varía de colisión a colisión.

Una vez que haya identificado la parte que se repite, seleccione una función que es algo inusual y búsquela en your defect database.

For example, una serialización ArrayList predeterminada.

Aquí su GrahPanel refiere un Simulation que se refiere a Graph, con potencialmente larga ArrayList del sensor y Edge ...

Java serialización mantiene un registro de todos los objetos escrito a un arroyo. Si el mismo objeto se encuentra por segunda vez, solo se escribe una referencia a él en la secuencia, y no una segunda copia del objeto; así que las referencias circulares no son el problema aquí.

Pero la serialización es vulnerable al desbordamiento de la pila para ciertos tipos de estructuras; por ejemplo, , una lista larga enlazada sin métodos especiales writeObject() se serializará escribiendo recursivamente cada enlace. Si tiene 100.000 enlaces, intentará utilizar 100.000 marcos de pila, y es muy probable que falle con StackOverflowError.

Es posible definir un método writeObject() para una clase de lista tal que, cuando se serializa el primer enlace, simplemente recorre la lista y serializa cada enlace de forma iterativa; esto evitará que se use el mecanismo recursivo por defecto.

1

Tiene algunas ArrayLists profundamente anidadas.

Creo que tal vez se trata solo de profundizar primero, y eso significa que está yendo para el sensor inferior, que es demasiado profundo.

¿Tal vez podría crear una estructura personalizada con sensores comenzando por el sensor inferior?

¿O tal vez tendrá que proporcionar su propia serialización para manejarlo? http://java.sun.com/developer/technicalArticles/Programming/serialization/

0

Debe crear una clase de contenedor para los objetos que desea almacenar. No almacenaría el objeto completo con toda la lógica dentro.

Almacene el primer campo por campo para encontrar el elemento que es grande para almacenarlo de esa manera. Luego ponga un punto de interrupción en el método y observe el elemento de campo. ¿El elemento contiene enlaces que se vinculan entre sí?

2

Debería considerar volver a implementar los métodos writeObject/readObject de su clase de Simulación con el fin de serializar solo los datos relevantes (y no toda la estructura de objetos contenidos por defecto) o etiquetar objetos transitorios no serializados. También puede usar la interfaz Externalizable si es necesario.

BTW, es posible que desee leer este interesting article para comenzar.

0

Y una vez que haya hecho todo eso simplemente use XStream en su lugar si solo desea guardar en un archivo.

0

ejecutar Java con las pilas más grandes

0

Este código debería servir como modelo, ya que soluciona el problema de stackoverflow en la serialización. Utiliza la memoria en el lugar de la recursión. Aunque no es apto para ser considerado universal como un serializador, serializa y deserializa las clases con las que se probó.

import java.io.*; 
import java.util.*; 
import java.lang.reflect.*; 
import android.util.*; 

public class SequentialObjectInputStream extends DataInputStream implements ObjectInput 
{ 
    interface FieldPutAction 
    { 
     void put(Object obj, Field field) throws IllegalAccessException, IOException; 
    } 

    interface ArrayPutAction 
    { 
     void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException; 
    } 

    public HashMap<Class, FieldPutAction> Primatives; 
    public HashMap<Class, ArrayPutAction> ArrayPrimatives; 

    public SequentialObjectInputStream(InputStream stream) 
    { 
     super(stream); 

     Primatives = new HashMap<Class, FieldPutAction>(); 

     try 
     { 
      Primatives.put(boolean.class, 
       new FieldPutAction() 
       { 
        public void put(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         boolean x = readBoolean(); 
         field.setBoolean(obj, x); 

        } 
       }); 

      Primatives.put(byte.class, 
       new FieldPutAction() 
       { 
        public void put(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         byte x = readByte(); 
         field.setByte(obj, x); 

        } 
       }); 


      Primatives.put(short.class, 
       new FieldPutAction() 
       { 
        public void put(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         short x = readShort(); 
         field.setShort(obj, x); 

        } 
       }); 


      Primatives.put(int.class, 
       new FieldPutAction() 
       { 
        public void put(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         int x = readInt(); 
         field.setInt(obj, x); 

        } 
       }); 


      Primatives.put(long.class, 
       new FieldPutAction() 
       { 
        public void put(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         long x = readLong(); 
         field.setLong(obj, x); 

        } 
       }); 


      Primatives.put(char.class, 
       new FieldPutAction() 
       { 
        public void put(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         char x = readChar(); 
         field.setChar(obj, x); 

        } 
       }); 


      Primatives.put(float.class, 
       new FieldPutAction() 
       { 
        public void put(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         float x = readFloat(); 
         field.setFloat(obj, x); 

        } 
       }); 


      Primatives.put(double.class, 
       new FieldPutAction() 
       { 
        public void put(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         double x = readDouble(); 
         field.setDouble(obj, x); 

        } 
       }); 


      Primatives.put(String.class, 
       new FieldPutAction() 
       { 
        public void put(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         String x = readUTF(); 
         field.set(obj, x); 

        } 
       }); 
     } catch(Exception e) 
     { 
      Log.e("SOb", Log.getStackTraceString(e)); 
     } 

     ArrayPrimatives = new HashMap<Class, ArrayPutAction>(); 

     try 
     { 
      ArrayPrimatives.put(boolean.class, 
       new ArrayPutAction() 
       { 
        public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         boolean x = readBoolean(); 
         Array.setBoolean(obj, index, x); 
        } 
       }); 

      ArrayPrimatives.put(byte.class, 
       new ArrayPutAction() 
       { 
        public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         byte x = readByte(); 
         Array.setByte(obj, index, x); 

        } 
       }); 


      ArrayPrimatives.put(short.class, 
       new ArrayPutAction() 
       { 
        public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         short x = readShort(); 
         Array.setShort(obj, index, x); 

        } 
       }); 


      ArrayPrimatives.put(int.class, 
       new ArrayPutAction() 
       { 
        public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         int x = readInt(); 
         Array.setInt(obj, index, x); 

        } 
       }); 


      ArrayPrimatives.put(long.class, 
       new ArrayPutAction() 
       { 
        public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         long x = readLong(); 
         Array.setLong(obj, index, x); 

        } 
       }); 


      ArrayPrimatives.put(char.class, 
       new ArrayPutAction() 
       { 
        public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         char x = readChar(); 
         Array.setChar(obj, index, x); 

        } 
       }); 


      ArrayPrimatives.put(float.class, 
       new ArrayPutAction() 
       { 
        public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         float x = readFloat(); 
         Array.setFloat(obj, index, x); 

        } 
       }); 


      ArrayPrimatives.put(double.class, 
       new ArrayPutAction() 
       { 
        public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         double x = readDouble(); 
         Array.setDouble(obj, index, x); 

        } 
       }); 


      ArrayPrimatives.put(String.class, 
       new ArrayPutAction() 
       { 
        public void put(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         String x = readUTF(); 
         Array.set(obj, index, x); 

        } 
       }); 
     } catch(Exception e) 
     { 
      Log.e("SOb", Log.getStackTraceString(e)); 
     } 
    } 


    @Override 
    public Object readObject() throws ClassNotFoundException, IOException 
    { 
     long Total = readLong(); 

     Log.i("SOb", "readObject : " + Long.toString(Total) + " objects in graph"); 

     HashMap<Long, Object> References = new HashMap<Long, Object>(); 

     long currentId = 1; 

     HashMap<Object, HashMap<Field, Long>> refCache = 
      new HashMap<Object, HashMap<Field, Long>>(); 
     final HashMap<Object, HashMap<Integer, Long>> arefCache = 
      new HashMap<Object, HashMap<Integer,Long>>(); 

     for (int I=0; I < Total; I++) 
     { 
      String Name = readUTF(); 
      Class C = Class.forName(Name); 

      Log.i("SOb", "Object of "+C.getCanonicalName() +" on graph"); 

      int adim = 0; 

      Object O = null; 

      if (C.isArray()) 
      { 
       Class ComponentType = C.getComponentType(); 

       int Size = readInt(); 

       Log.i("SOb", "array of "+ComponentType.getCanonicalName() + ", " + Long.toString(Size) + " elements");   
       O = Array.newInstance(ComponentType, Size); 

       References.put(currentId, O); 
       currentId++; 

       ArrayPutAction action = null; 

       if (ArrayPrimatives.keySet().contains(ComponentType)) 
       { 
        action = ArrayPrimatives.get(ComponentType); 
       } else 
       { 
        arefCache.put(O, new HashMap<Integer, Long>()); 

        action = new ArrayPutAction() 
        { 
         public void put(Object O, int Index) throws ArrayIndexOutOfBoundsException , IOException 
         { 
          long Ref = readLong(); 

          arefCache.get(O).put(Index, Ref); 
         } 
        }; 
       } 

       for (int index=0; index< Size; index++) 
       { 
        action.put(O,index); 
       } 

      } else 
      { 

      try 
      { 

       O = 
        C.getConstructor(new Class[0]).newInstance(new Object[0]); 
      } catch(InstantiationException e) 
      { 
       Log.e("SOb", Log.getStackTraceString(e)); 
      } catch(NoSuchMethodException e) 
      { 
       Log.e("SOb", Log.getStackTraceString(e)); 
      } catch(IllegalAccessException e) 
      { 
       Log.e("SOb", Log.getStackTraceString(e)); 
      } catch(InvocationTargetException e) 
      { 
       Log.e("SOb", Log.getStackTraceString(e)); 
      } 

      References.put(currentId, O); 
      currentId++; 
      refCache.put(O, new HashMap<Field, Long>()); 

      for (Field F : C.getFields()) 
      { 
       if (F.isAccessible()) 
       { 
        Class T = F.getType(); 

        if (Primatives.containsKey(T)) 
        { 
         try 
         { 
          Primatives.get(T).put(O, F); 
         } catch (IllegalAccessException e) 
         { 

         } 
        } else 
        { 
         refCache.get(O).put(F, readLong()); 
        } 
       } 
      } 

     } 
     } 
     for (long I=0; I < Total; I++) 
     { 

      Object O = References.get(I+1); 

      Class C = O.getClass(); 

      //Log.i("SOb", "get reference "+Long.toString(I)+" "+C.getCanonicalName()); 


      if (C.isArray()) 
      { 
       HashMap<Integer,Long> aref_table = arefCache.get(O); 

       if (ArrayPrimatives.containsKey(C.getComponentType()) == false) 
       { 

        int len = Array.getLength(O); 

        for (int index=0; index<len; index++) 
        { 
         long r = aref_table.get(index); 
         Object ref = r == 0 ? null : References.get(r); 

         Array.set(O, index, ref); 
        } 
       } 

      } else 
      { 

      HashMap<Field, Long> ref_table = refCache.get(O); 

      for (Field F : C.getFields()) 
      { 
       if (F.isAccessible()) 
       { 
        Class T = F.getType(); 

        if (Primatives.containsKey(T) == false) 
        { 
         try 
         { 
          long r = ref_table.get(F); 
          Object ref = r == 0 ? null : References.get(r); 

          F.set(O, ref); 
         } catch (IllegalAccessException e) 
         { 
          Log.e("SOb", Log.getStackTraceString(e)); 
         } 

        } 
       } 
      } 
      } 

     } 


     return References.get((Long) (long) 1); 
    } 

} 


import java.io.*; 
import java.util.*; 
import java.lang.reflect.*; 
import android.util.*; 

public class SequentialObjectOutputStream extends DataOutputStream 
implements ObjectOutput 
{ 
    interface FieldGetAction 
    { 
     void get(Object obj, Field field) throws IllegalAccessException, IOException; 
    } 

    interface ArrayGetAction 
    { 
     void get(Object array, int Index) throws ArrayIndexOutOfBoundsException, IOException;  
    } 

    public HashMap<Class, FieldGetAction> Primatives; 
    public HashMap<Class, ArrayGetAction> ArrayPrimatives; 

    public SequentialObjectOutputStream(OutputStream stream) 
    { 
     super(stream); 

     Primatives = new HashMap<Class, FieldGetAction>(); 

     try 
     { 
      Primatives.put(boolean.class, 
      new FieldGetAction() 
      { 
       public void get(Object obj, Field field) throws IllegalAccessException, IOException 
       { 
        boolean x = field.getBoolean(obj); 
        writeBoolean(x); 

       } 
      }); 

      Primatives.put(byte.class, 
       new FieldGetAction() 
       { 
        public void get(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         byte x = field.getByte(obj); 
         writeByte(x); 

        } 
       }); 


      Primatives.put(short.class, 
       new FieldGetAction() 
       { 
        public void get(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         short x = field.getShort(obj); 
         writeShort(x); 

        } 
       }); 


      Primatives.put(int.class, 
       new FieldGetAction() 
       { 
        public void get(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         int x = field.getInt(obj); 
         writeInt(x); 

        } 
       }); 


      Primatives.put(long.class, 
       new FieldGetAction() 
       { 
        public void get(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         long x = field.getLong(obj); 
         writeLong(x); 

        } 
       }); 


      Primatives.put(char.class, 
       new FieldGetAction() 
       { 
        public void get(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         char x = field.getChar(obj); 
         writeChar(x); 

        } 
       }); 


      Primatives.put(float.class, 
       new FieldGetAction() 
       { 
        public void get(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         float x = field.getFloat(obj); 
         writeFloat(x); 

        } 
       }); 


      Primatives.put(double.class, 
       new FieldGetAction() 
       { 
        public void get(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         double x = field.getDouble(obj); 
         writeDouble(x); 
        } 
       }); 


      Primatives.put(String.class, 
       new FieldGetAction() 
       { 
        public void get(Object obj, Field field) throws IllegalAccessException, IOException 
        { 
         String x = (String) field.get(obj); 
         writeUTF(x); 

        } 
       }); 
     } catch(Exception e) 
     { 
      Log.e("SOb", Log.getStackTraceString(e)); 
     } 



     ArrayPrimatives = new HashMap<Class, ArrayGetAction>(); 

     try 
     { 
      ArrayPrimatives.put(boolean.class, 
       new ArrayGetAction() 
       { 
        public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         boolean x = Array.getBoolean(obj, index); 
         writeBoolean(x); 

        } 
       }); 

      ArrayPrimatives.put(byte.class, 
       new ArrayGetAction() 
       { 
        public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         byte x = Array.getByte(obj, index); 
         writeByte(x); 

        } 
       }); 


      ArrayPrimatives.put(short.class, 
       new ArrayGetAction() 
       { 
        public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         short x = Array.getShort(obj, index); 
         writeShort(x); 

        } 
       }); 


      ArrayPrimatives.put(int.class, 
       new ArrayGetAction() 
       { 
        public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         int x = Array.getInt(obj, index); 
         writeInt(x); 

        } 
       }); 


      ArrayPrimatives.put(long.class, 
       new ArrayGetAction() 
       { 
        public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         long x = Array.getLong(obj, index); 
         writeLong(x); 

        } 
       }); 


      ArrayPrimatives.put(char.class, 
       new ArrayGetAction() 
       { 
        public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         char x = Array.getChar(obj, index); 
         writeChar(x); 

        } 
       }); 


      ArrayPrimatives.put(float.class, 
       new ArrayGetAction() 
       { 
        public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         float x = Array.getFloat(obj, index); 
         writeFloat(x); 

        } 
       }); 


      ArrayPrimatives.put(double.class, 
       new ArrayGetAction() 
       { 
        public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         double x = Array.getDouble(obj, index); 
         writeDouble(x); 
        } 
       }); 


      ArrayPrimatives.put(String.class, 
       new ArrayGetAction() 
       { 
        public void get(Object obj, int index) throws ArrayIndexOutOfBoundsException, IOException 
        { 
         String x = (String) Array.get(obj, index); 
         writeUTF(x); 

        } 
       }); 
     } catch(Exception e) 
     { 
      Log.e("SOb", Log.getStackTraceString(e)); 
     } 

    } 

    class State 
    { 
     public ArrayList<Object> OStack = new ArrayList<Object>(); 

     public long currentId = 1; 

     public HashMap<Object, Long> References = new HashMap<Object, Long>(); 

    } 

    public void writeObject(Object A) throws IOException, NotSerializableException 
    { 
     final State state = new State(); 

     state.OStack.add(0, A); 

     LinkedList<Object> ForStack = new LinkedList<Object>(); 

     while (!(state.OStack.size() == 0)) 
     { 
      Object Current = state.OStack.get(0); 
      state.OStack.remove(0); 

      if (((Serializable) Current) == null) 
      { 
       throw new NotSerializableException(); 
      } 


      //Type C = Current.getClass(); 

      Class C = Current.getClass(); 

      Log.i("SOb", "placing #"+Long.toString(state.currentId)+" of "+C.getCanonicalName()+" on graph"); 
      state.References.put(Current, state.currentId); 
      state.currentId++; 

      ForStack.add(Current); 

      if (C.isArray()) 
      { 
       //Array array = (Array) Current; 
       Class Ctype = C.getComponentType(); 

       if (ArrayPrimatives.keySet().contains(Ctype) == false) 
       { 
        for (int I=0; I<Array.getLength(Current); I++) 
        { 
         Object o = Array.get(Current, I); 

         if ((o != null) && (state.References.keySet().contains(o) == false)) 
         { 
          if (state.OStack.contains(o) == false) state.OStack.add(state.OStack.size(), o); 
         } 

        } 
       } 
      } else 
      { 
       for (Class Cur = C; Cur != null; Cur = Cur.getSuperclass()) 
       { 

        Field[] fields = Cur.getDeclaredFields(); 

        for (Field f : fields) 
        { 
         if (Modifier.isStatic(f.getModifiers())) 
         { 
          continue; 
         } 

         f.setAccessible(true); 

         if (f.isAccessible() == false) 
         { 
         // Log.i("SOb", "  isAccessible = false"); 
          continue; 
         } 

         Class type = f.getType(); 
         //Log.i("SOb", "  field \""+f.getName()+"\" of "+type.getCanonicalName()); 

         if (Primatives.keySet().contains(type) == false) 
         {  
          try 
          { 
           Object o = f.get(Current); 

           if ((o != null) && (state.References.keySet().contains(o) == false)) 
           { 
            if (state.OStack.contains(o) == false) state.OStack.add(state.OStack.size(), o); 
           } 

          } catch (IllegalAccessException e) 
          { 
           Log.e("SOb", Log.getStackTraceString(e)); 
          } 
         } 
        } 
       } 
      } 
     } 

     writeLong(state.References.size()); 

     for (Object O : ForStack) 
     { 
      Serializable s = (Serializable) O; 

     // if (s != null) 
      { 
       Class cl = O.getClass(); 

       String name = cl.getName(); 

       writeUTF(name); 

       if (cl.isArray()) 
       { 
        Class components = cl.getComponentType(); 

        ArrayGetAction action; 

        //Array array = (Array) O; 

        if (ArrayPrimatives.keySet().contains(components)) 
        { 
         action = ArrayPrimatives.get(components); 
        } else 
        { 
         action = new ArrayGetAction() 
         { 
          public void get(Object array, int index) throws ArrayIndexOutOfBoundsException, IOException  
          { 
           Object O = Array.get(array, index); 
           if (O==null) writeLong(0); 
           else writeLong(state.References.get(O)); 
          } 
         }; 
        } 

        int length = Array.getLength(O); 

        writeInt(length); 

        for (int I=0; I<length; I++) 
        { 
         action.get(O, I); 
        } 

       } else 
       { 
        for (Class Cur = cl; Cur != null; Cur = Cur.getSuperclass()) 
        { 
         Field[] fields = Cur.getDeclaredFields(); 

         for (Field F : fields) 
         { 
          Class FieldType = F.getType(); 

          F.setAccessible(true); 

          if (F.isAccessible() && (Modifier.isStatic(FieldType.getModifiers()))) 
          { 
           FieldGetAction action; 

           //Array array = (Array) O; 

           if (Primatives.keySet().contains(FieldType)) 
           { 
            action = Primatives.get(FieldType); 
           } else 
           { 
            action = new FieldGetAction() 
            { 
             public void get(Object obj, Field index) throws IllegalAccessException, IOException  
             { 
              Object O = index.get(obj); 
              if (O==null) writeLong(0); 
              else writeLong(state.References.get(O)); 
             } 
            }; 
           } 

           try 
           { 
            action.get(O, F); 
           } catch (IllegalAccessException e) 
           { 
            Log.e("SOb", Log.getStackTraceString(e)); 
           } 

          } 
         } 

        } 
       } 
      } 
     } 
    } 
} 
+0

Eso es mucho código, sin explicación sobre cómo responde la pregunta. ¿Podría agregar una pequeña descripción de lo que está haciendo? – andrewsi

+0

Durante la serialización, se utilizan 2 pases. El primero agrega cada objeto único a una lista de objetos y crea un índice para cada objeto. El segundo pase. serializa una vista plana del objeto con el índice utilizado en lugar del valor de un campo o valor de matriz. De esta forma, cuando se procesa la lista de objetos, hay una asignación plana del objeto serializado y sus referencias sin usar un objeto de escritura recursivo. – RofaMagius

Cuestiones relacionadas