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:
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 sale el siguiente error (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 puede decirme qué está causando esta excepción?
Publicación interesante de Chen:
Al depurar un desbordamiento de stack, desea centrarse en la parte repetitiva recursiva
En tu 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 busca en la base de datos de seguimiento de defectos para ver si se trata de un problema conocido o no, es poco probable que la búsqueda de las funciones superiores en la stack encuentre algo interesante. Eso es porque los desbordamientos de stack tienden a ocurrir en un punto aleatorio en la recursión; cada desbordamiento de stack se ve superficialmente diferente de todos los demás, incluso si son del mismo desbordamiento de stack.
Una vez que superas la confusión inicial, la traza de la stack 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 golpe a golpe.Una vez que haya identificado la parte que se repite, seleccione una función que sea algo inusual y búsquela en su base de datos de defectos .
Por ejemplo , una serialización ArrayList
predeterminada.
Aquí su GrahPanel
refiere a una Simulation
que hace referencia a Graph
, con ArrayList
de Sensor y Edge potencialmente largos …
La serialización de Java mantiene un registro de cada objeto escrito en una secuencia. 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 stack para ciertos tipos de estructuras; por ejemplo, una lista enlazada larga sin métodos especiales writeObject () se serializará escribiendo recursivamente cada enlace. Si tiene 100.000 enlaces, intentará utilizar 100.000 marcos de stack, y es muy probable que falle con StackOverflowError .
Es posible definir un método writeObject () para dicha clase de lista que, cuando el primer enlace se serializa, simplemente recorre la lista y serializa cada enlace de forma iterativa; esto evitará que se use el mecanismo recursivo por defecto.
Debería considerar writeObject
readObject
métodos writeObject
/ readObject
de su clase de Simulación para serializar solo los datos relevantes (y no toda la estructura de objetos contenidos por defecto) o etiquetar transitorios para que no sean objetos serializados. También puede usar la interfaz Externalizable
si es necesario.
Por cierto, es posible que desee leer este interesante artículo para comenzar.
Tienes ArrayLists profundamente nesteds.
Creo que tal vez es solo profundizar primero, y eso significa que está yendo para el sensor inferior, que es demasiado profundo.
¿Tal vez podrías crear una estructura personalizada con sensores comenzando con el sensor inferior?
¿O tal vez deberás proporcionar tu propia serialización para manejarlo? http://java.sun.com/developer/technicalArticles/Programming/serialization/
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 inflexión en el método y eche un vistazo al elemento de campo. ¿El elemento contiene enlaces que se vinculan entre sí?
Y después de que haya hecho todo eso solo use XStream en su lugar si solo desea guardar en un archivo.
Ejecuta Java con stacks más grandes
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 Primatives; public HashMap ArrayPrimatives; public SequentialObjectInputStream(InputStream stream) { super(stream); Primatives = new HashMap(); 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(); 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 References = new HashMap(); long currentId = 1; HashMap
Tuve un problema similar. Después de mucha caza, encontré una horquilla de Kryo diseñada para manejar objetos profundamente nesteds. A través de https://github.com/EsotericSoftware/kryo/issues/103 , clone and mvn clean install
https://github.com/romix/kryo/tree/kryo-2.23-continuations . Actualmente es com.esotericsoftware.kryo:kryo:2.23-SNAPSHOT
.