Sachin Verma
Sachin Verma

Reputation: 3802

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 ?

Upvotes: 3

Views: 6768

Answers (2)

Stephen C
Stephen C

Reputation: 718826

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.

Upvotes: 9

Thilo
Thilo

Reputation: 262514

Does every thread has 3000k stack size if I put a JVM option of -Xss3000k ?

There is a constructor to specify the stack size for the new Thread. All threads that don't use that special constructor will get the default stack size specified in the JVM option (and that will cover all threads unless you create them yourself explicitly).

If your application does not need a great number of threads, the raised limit is probably not a problem and the easiest solution.

If not, you may want to construct such a big-stack thread especially for running your deeply recursive serialization code. You can wrap it up into an Executor and have application code call into it.

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

That is indeed a bit of a moving target. You should make this configurable and experimentation will tell you what a good setting is.

Even the Javadoc says

Due to the platform-dependent nature of the behavior of this constructor, extreme care should be exercised in its use. The thread stack size necessary to perform a given computation will likely vary from one JRE implementation to another. In light of this variation, careful tuning of the stack size parameter may be required, and the tuning may need to be repeated for each JRE implementation on which an application is to run.

Upvotes: 2

Related Questions