StackOverflowError when serializing an object in Java

后端 未结 8 1603
眼角桃花
眼角桃花 2020-11-28 13:56

I am writing an application in Java using Swing. I am trying to implement functionality to save and load simulation states for at simulation i am running. The entire simulat

相关标签:
8条回答
  • 2020-11-28 14:32

    You should create a container class for the objects you want to store. I would not store the complete this object with all the logic inside.

    Store first field by field to find the element which is to big to store it that way. Than put a breakpoint in the methode and take a look at the field element. Does the element contains links which link to each other?

    0 讨论(0)
  • 2020-11-28 14:39

    This code should serve as a model, as it addresses the problem of stackoverflow on serialization. It uses memory inplace of recursion. Although not fit to be concidered universal as a serializer, it serializes and deserializes the classes it was tested with.

    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 讨论(0)
提交回复
热议问题