JDK-4152790 : StackOverFlowError serializing/deserializing a large graph of objects.
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.io:serialization
  • Affected Version:
    1.0,1.1.6,1.1.7,1.3.0,1.3.0_01,1.4.2,5.0u9 1.0,1.1.6,1.1.7,1.3.0,1.3.0_01,1.4.2,5.0u9
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS:
    generic,solaris_2.5,windows_nt,windows_2000,windows_xp generic,solaris_2.5,windows_nt,windows_2000,windows_xp
  • CPU: generic,x86
  • Submitted: 1998-06-26
  • Updated: 2014-08-28
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Description
Summary: Serializing recursively calls writeObject, resulting in 
         java.lang.StackOverFlowError being thrown when the
         object graph is deeply nested (example: long link list).
         Since serialiation is being performed on a server
         that spawns a thread for each client, it is not possible
	 to up the stack size to workaround this capacity limitation for
	 each thread.

Customer mail message:

Apparently an object O is serialized in a "pre-order" walk of the
object graph rooted at O. Thus if O points to O', O' is
serialized first, and then O. JDK 1.1.6 and earlier versions seem
to implement this by using the stack to do the recursion.

This has the hugely unfortunate property of limiting the size of
the graphs that can be serialized. Trying to serialize a linked
list of 1000 elements blew my stack on an WinNT! In essence, one
cannot serialize an object graph which can grow arbitrarily
large.

I am led to believe that it is not possible in Java to grow the
stack size arbitrarily in a data-dependent manner from inside the
JVM. Why not do this recursion in the heap then?

Or, perhaps even better, why not do the serialization in a
"post-order" walk (generating a handle on O', stashing that away
in a table, finishing the serialization of O (using the handle
for all future accesses to O') and then coming back to serialize
all the objects in the table that have not yet been serialized)?

Are any patches available for this functionality? I can try to
fake it in my application, but the problem is that I do not
control the code being loaded into the JVM --- so I cannot
control the {write/read}Object methods for all classes.


Comments
WORK AROUND The recommended work-around is to define custom writeObject and readObject methods which transmit the nested/linked data structures as a flat sequence of objects. One example of this is the writeObject/readObject methods of java.util.LinkedList. The following post to the rmi-users mailing list explains another (similar) example: http://swjscmail1.java.sun.com/cgi-bin/wa?A2=ind9909&L=rmi-users&F=&S=&P=34494
02-10-2004

EVALUATION The cause of this problem is well-known. It looked like a practical work-around existed of upping the native stack size. However, this workaround is not sufficent when many threads all all trying to serialize. More thought should be given to use heap space over stack space to serialize a graph of objects. This is too risky a change to make for JDK 1.2, but needs to be considered in the future. joseph.fialli@East 1998-06-26 Will fix for merlin. The new mechanism wouuld switch from a recursive algorithm to an iterative one at a predetermined recursion depth. See comments. naveen.sanjeeva@eng 2000-06-15 Not enough time/resources to fix this for merlin. Will leave open for consideration in a future release. michael.warres@east 2000-12-27
15-06-2000