StackOverflowError when serializing an object in Java

后端 未结 8 1650
眼角桃花
眼角桃花 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: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 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> refCache =
                new HashMap>();
            final HashMap> arefCache =
                new HashMap>();
    
            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());
    
                        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());
    
                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 aref_table = arefCache.get(O);
    
                    if (ArrayPrimatives.containsKey(C.getComponentType()) == false)
                    {
    
                        int len = Array.getLength(O);
    
                        for (int index=0; index 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 Primatives;
        public HashMap ArrayPrimatives;
    
        public SequentialObjectOutputStream(OutputStream stream)
        {
            super(stream);
    
            Primatives = new HashMap();
    
            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();
    
            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 OStack = new ArrayList();
    
            public long currentId = 1;
    
            public HashMap References = new HashMap();
    
        }
    
        public void writeObject(Object A) throws IOException, NotSerializableException
        {
            final State state = new State();
    
            state.OStack.add(0, A);
    
            LinkedList ForStack = new LinkedList();
    
            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
        

    提交回复
    热议问题