Search code examples
javajvmjvm-hotspot

JVM stack size specifications


I have a regular 64-bit hotspot JVM which has 1 MB stack size. Now I was trying to serialize an object that has hierarchy of 3022 parents and this is giving me SO(irony) exception.

Here's some code:

while(epc.getParent()!=null){

      epc=epc.getParent();
      count++;
     }
     print(count);//3022

Above code is just to tell the hierarchy but the actual problem occurs when I try to serialize the epc object onto ObjectOutputStream.

Question, what does 1 MB stack size states in JVM as I have no idea what size a stack frame of? I'm sure it's not 1KB per stack frame because I ran about code successfully at -Xss3000k.

One more question, does every thread has 3000k stack size if I put a JVM option of -Xss3000k ?


Solution

  • Question, what does 1 MB stack size states in JVM as I have no idea what size a stack frame of?

    A 1 MB default thread stack size means that every thread has 1MB (1048576 bytes) of stack space ... by default. The exception is if your code creates a thread using one of the Thread constructors where you can provide a stack size argument.

    The size of a stack frame depends on the method being called. It needs to hold the method's parameters and local variables, so the frame size depends on their size. Each frame also needs (I think) two extra words to hold a saved frame pointer and a saved return address.

    Note that in a recursive algorithm, you can have more than one stack frame for one "level of recursion". For writeObject (in Java 8), the algorithm used is recursive, and there are typically 4 frames per level of the data structure being serialized:

    writeObject0 
    writeOrdinaryObject
    writeSerialData
    defaultWriteFields
    writeObject0
    etcetera
    

    The actual frame sizes will be platform dependent due to differences in compilers, and changes in the implementation of ObjectInputStream / ObjectOutputStream. You would better off trying to (roughly) measure the required stackspace rather than trying to predict frame sizes from first principles.

    One more question, does every thread has 3000k stack size if I put a JVM option of -Xss3000k ?

    Yes ... with the exception that I have described above.

    One possible solution to your dilemma is create a special thread with an huge stack that you use for serialization. A similar thread with a huge stack will be required for deserialization. For the rest of the threads, the default stack size should be fine.

    Other possible solutions:

    • Implement writeReplace and readResolve methods to flatten the parent structure of your epc objects into an array so that you don't get deep recursion. (Obviously, the flattening / unflattening needs to be done non-recursively.)

    • Do the same flattening before you call writeObject, etcetera.

    • Use a different serialization mechanism, or possible a custom one.