在Java中序列化对象时的StackOverflowError

我正在使用Swing在Java中编写应用程序。 我正在尝试实现function,以保存和加载模拟状态,在我正在运行的模拟。 整个模拟保持为一个对象,与Swing断开连接。 我想用这段代码序列化我的模拟类:

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

但我得到以下错误(这是巨大的)。

 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) 

有谁能告诉我是什么原因造成这个exception?

陈的有趣post:

debugging堆栈溢出时,您需要关注重复的recursion部分

在你的情况下:

  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) 

如果你通过你的缺陷跟踪数据库去寻找这个问题是否是已知的问题,那么search堆栈顶部的函数是不太可能发现任何有趣的。 这是因为堆栈溢出往往发生在recursion中的一个随机点。 即使堆栈溢出相同,每个堆栈溢出看起来都与表面上不同。

一旦你经历了最初的混乱,堆栈轨迹一次又一次地稳定到一个包含相同x函数的好的重复模式。
识别重复模式的开始并不重要,因为每次碰撞的起始点都不相同,就像超出你的演唱范围的精确音符从碰撞到碰撞一样。

一旦确定了重复部分,从中select一个有点不寻常的function,并在缺陷数据库中进行search。

例如 ,默认的ArrayList序列化。

在这里你的GrahPanel引用一个Simulation ,它涉及到Graph ,可能长的传感器和边缘ArrayList

Java序列化保存了写入stream的每个对象的logging。 如果再次遇到同一个对象,则只有对该对象的引用被写入到stream中,而不是该对象的第二个副本; 所以循环引用不是这里的问题。

但是对于某些types的结构,序列化很容易发生堆栈溢出; 例如, 没有特殊的writeObject()方法的长链表将通过recursion地写入每个链接而被序列化。 如果你有10万个链接,你将尝试使用10万个堆栈帧,很可能会因为StackOverflowError而失败

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

你应该考虑重新实现你的Simulation类的writeObject / readObject方法,以便只序列化相关数据(而不是默认的整个包含的对象结构),或者标记暂时不被序列化的对象。 如果需要,您也可以使用Externalizable接口。

顺便说一句,你可能想阅读这个有趣的文章开始。

你有一些深嵌套的ArrayLists。

我认为也许这只是深入的第一步,这意味着它的底部传感器,这是太深了。

也许你可以创build一个自底部传感器开始的传感器自定义结构?

或者,也许你将不得不提供自己的序列化来处理它? http://java.sun.com/developer/technicalArticles/Programming/serialization/

您应该为要存储的对象创build一个容器类。 我不会存储完整的这个对象与所有的逻辑里面。

先存储第一个字段,find要存储的那个元素。 在方法中放置一个断点并查看字段元素。 元素是否包含相互链接的链接?

而且,如果只想保存到文件中,则只需使用XStream即可。

用更大的堆栈运行java

我有一个类似的问题。 经过多次的狩猎之后,我发现了一个Kryo的叉子,用来处理深度嵌套的物体。 通过https://github.com/EsotericSoftware/kryo/issues/103 ,克隆和mvn clean install https://github.com/romix/kryo/tree/kryo-2.23-continuations 。 目前是com.esotericsoftware.kryo:kryo:2.23-SNAPSHOT

这个代码应该作为一个模型,因为它解决了序列化时的计算器的问题。 它使用recursion内存。 虽然不适合作为序列化程序被广泛使用,但它会对testing的类进行序列化和反序列化。

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