Question

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 simulation is kept as an object, disconnected from Swing. I am trying to serialize my Simulation class with this code:

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

But i get the following error (it is huge).

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)

Can anybody tell me what is causing this exception?

Was it helpful?

Solution

Interesting post from Chen:

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

In your case:

        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)

If you go hunting through your defect tracking database trying to see whether this is a known issue or not, a search for the top functions on the stack is unlikely to find anything interesting. That's because stack overflows tend to happen at a random point in the recursion; each stack overflow looks superficially different from every other one even if they are the same stack overflow.

Once you get past the initial turmoil, the stack trace settles down into a nice repeating pattern consisting of the same x functions over and over again.
Identifying the start of the repeating pattern isn't important, because the starting point will be different for each crash, in the same way that the precise note which exceeds your singing range varies from crash to crash.

Once you've identified the repeating part, pick a function from it that is somewhat unusual and search for it in your defect database.

For example, an default ArrayList serialization.

Here your GrahPanel refers a Simulation which refers to Graph, with potentially long ArrayList of Sensor and Edge...

Java serialization keeps a record of every object written to a stream. If the same object is encountered a second time, only a reference to it is written to the stream, and not a second copy of the object; so circular references aren't the problem here.

But serialization is vulnerable to stack overflow for certain kinds of structures; for example, a long linked list with no special writeObject() methods will be serialized by recursively writing each link. If you've got a 100,000 links, you're going to try to use 100,000 stack frames, and quite likely fail with a StackOverflowError.

It's possible to define a writeObject() method for such a list class that, when the first link is serialized, simply walks the list and serializes each link iteratively; this will prevent the default recursive mechanism from being used.

OTHER TIPS

You should consider reimplementing the writeObject / readObject methods of your Simulation class in order to serialize only the relevant data (and not the entire contained object structure by default) or tagging transient your not to be serialized objects. You can also use the Externalizable interface if needed.

BTW, you may want to read this interesting article to begin with.

You've got some deeply nested ArrayLists.

I think maybe it's just going depth first, and that means it's going for the bottom Sensor, which is too deep.

Maybe you could create a custom structure with Sensors starting with the bottom Sensor?

Or maybe you'll have to provide your own serialisation to handle it? http://java.sun.com/developer/technicalArticles/Programming/serialization/

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?

And after you done all that just use XStream instead if you only want to save to a file.

Run java with bigger stacks

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

                            }
                        }

                    }
                }
            }   
        }
    }
}

I had a similar problem. After much hunting, I found a fork of Kryo designed to handle deeply nested objects. Via https://github.com/EsotericSoftware/kryo/issues/103 , clone and mvn clean install https://github.com/romix/kryo/tree/kryo-2.23-continuations . It's currently com.esotericsoftware.kryo:kryo:2.23-SNAPSHOT.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top