title: Serializing Java Object without StackOverflowError
body: <p>I have a quite large Java object that represents a graph, with vertices and edges, in memory. Each vertex has an <code>ArrayList</code> of other vertices that it is connected to (and has a <code>HashMap</code> data structure as well for other purposes). The graph can have a few thousand vertices, and many more edges.</p>
  
  <p>When trying to serialize the graph using Java's built-in serialization (<code>implements Serializable</code>, etc.), I always run into a <code>StackOverflowError</code>. Setting other attributes of the graph to <code>transient</code> does not help, and nor does setting the stack size to be larger (i.e. <code>-Xss1g</code> or <code>-Xss512m</code>).</p>
  
  <p>I would not think that I need to make a custom <code>writeObject</code> method since <code>ArrayList</code> and <code>HashMap</code> already have their own implementations, which are called upon serialization.</p>
  
  <p>My question is: is there a way to serialize a large Java object already in memory without getting a <code>StackOverflowError</code>?</p>
  
  <p><strong>Edit</strong>: Here is the stack trace:</p>
  
  <pre><code>Exception in thread "main" java.lang.StackOverflowError
  at java.lang.reflect.Method.invoke(Method.java:575)
  at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:950)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1482)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
  at java.util.ArrayList.writeObject(ArrayList.java:570)
  at sun.reflect.GeneratedMethodAccessor1.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:950)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1482)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
  at java.util.ArrayList.writeObject(ArrayList.java:570)
  at sun.reflect.GeneratedMethodAccessor1.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:950)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1482)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
  at java.util.ArrayList.writeObject(ArrayList.java:570)
  at sun.reflect.GeneratedMethodAccessor1.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:950)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1482)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
  at java.util.ArrayList.writeObject(ArrayList.java:570)
  at sun.reflect.GeneratedMethodAccessor1.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:950)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1482)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
  at java.util.ArrayList.writeObject(ArrayList.java:570)
  at sun.reflect.GeneratedMethodAccessor1.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:950)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1482)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
  at java.util.ArrayList.writeObject(ArrayList.java:570)
  at sun.reflect.GeneratedMethodAccessor1.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:950)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1482)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
  at java.util.ArrayList.writeObject(ArrayList.java:570)
  at sun.reflect.GeneratedMethodAccessor1.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:950)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1482)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
  at java.util.ArrayList.writeObject(ArrayList.java:570)
  at sun.reflect.GeneratedMethodAccessor1.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:950)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1482)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1159)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
  at java.util.ArrayList.writeObject(ArrayList.java:570)
  at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  // Many more lines after this
  </code></pre>
  
  <p>Here is an overview of my <code>Graph</code> class:</p>
  
  <pre><code>public class Graph implements Serializable {
  
  /**
   * 
   */
  private static final long serialVersionUID = -2632163054149021990L;
  private ArrayList&lt;Vertex&gt; vertices;
  
  private HashMap&lt;Integer, Set&lt;Vertex&gt;&gt; map;
  
  public Graph(int rowMax, int colMax)
  {
      map = new HashMap&lt;Integer, Set&lt;Vertex&gt;&gt;();
  
      this.vertices = new ArrayList&lt;Vertex&gt;();
  }
  
  public void connectVertices(Vertex u, Vertex v)
  {
      u.addNeighbor(v);
      v.addNeighbor(u);
  }
  
  // other unrelated methods after this
  </code></pre>
  
  <p>And here is my <code>Vertex</code> class:</p>
  
  <pre><code>public class Vertex implements Serializable {
  
  /**
   * 
   */
  private static final long serialVersionUID = 8520500010710631610L;
  public int row;
  public int col;
  private ArrayList&lt;Vertex&gt; neighbors; // may change this to Set&lt;Vertex&gt;
  
  public Vertex(int i, int j)
  {
      this.row = i;
      this.col = j;
      this.neighbors = new ArrayList&lt;Vertex&gt;();
  }
  
  public boolean addNeighbor(Vertex v)
  {
      this.neighbors.add(v);
      return true;
  }
  
  // unrelated methods after this
  </code></pre>
  
  <p><strong>Edit 2</strong>: Also, for graphs of smaller sizes, but that have "neighbors", do not have this problem.</p>