How Java uses the stack is basically undocumented. So we developers are left with finding out ourselves. Today I wrote some interesting test code, that delivers surprising results. For my tests I used Sun JDK 1.5.0_12 under RedHat Enterprise Linux 3.
First I wanted to know the stack size that the VM chooses for threads. I found that the ulimit -s
parameter has no direct influence on the stack size chosen by the VM. The default is apparently 512kb, and can be changed freely with the -Xss
and -XX:ThreadStackSize
parameters. But I could not find a difference in behaviour between those parameters. They appear to do the same thing. Further I found that this Linux machine is able to create new threads at a rate of about 5000 per second.
I performed these tests by creating new threads and setting them asleep in a blocking wait call immediately. I kept creating threads until the VM ran out of memory. With 512k stacks the number of threads was around 3700, for 256k stacks around 7300, for 128k around 13700. That leads to the following memory consumption by the stacks:
3700 x 512kB = 1850MB
7300 x 256kB = 1825MB
13700 x 128kB = 1713MB
Of course a 32-bit process is limited to 4GB of address space (minus 1 or 2 GB for the kernel). So it is only natural that the memory is close to these 2GB minus the heap size. (Note that Stack is never allocated from the heap.)
Next I tested how deep I could call into a recursive method until I get stack overflows. I did this by modifying the initial program, so that each thread would recurse into a method until it hit stack overflow, then fall asleep. The thread recorded the maximum recursion depth. That's where I got really weird results. Especially with the server VM the maximum depth varies over a wide range between 1750 and 5700 calls (128k stacks)! That's far from constant, which would have been my first guess. With the client VM the number is generally lower but doesn't vary that much: between 1100 and 1650.
Also the maximum depth seems to be lower at the beginning of the test and increases toward the end.
If someone wants to repeat my tests, here is the
test code
that I was using. I am very interested to get further insights on how exactly stack works in Java.