I'm trying to determine how much stack memory each method consumes when running. To do the task, I've devised this simple program that will just force a StackOverflowError
,
public class Main {
private static int i = 0;
public static void main(String[] args) {
try {
m();
} catch (StackOverflowError e) {
System.err.println(i);
}
}
private static void m() {
++i;
m();
}
}
printing an integer telling me how many times m()
was called. I've manually set the JVM's stack size(-Xss
VM parameter) to varying values (128k, 256k, 384k), obtaining the following values:
stack i delta
128 1102
256 2723 1621
384 4367 1644
delta was calculated by me, and it's the value between the last line's i and the current one's. As expected it is fixed. And there lies the problem. As I know the stack size memory increment was by 128k, that yields something like a 80byte memory use per call (which seems exaggerated).
Looking up m()
in BytecodeViewer's, we get a stack's max depth of 2. We know this is a static method and that there's no this
parameter passing, and that m()
has no arguments. We must also take into consideration the return address pointer. So there should be something like 3 * 8 = 24 bytes used per method call (I'm assuming 8 bytes per variable, which of course may be totally off. Is it?). Even if it's a bit more than that, let's say 48bytes, we're still far away from the 80bytes value.
I thought it could have something to do with memory alignment, but truth is that in that case we'd have a value of roughly 64 or 128 bytes, I'd say.
I'm running a 64bit JVM under a 64bit Windows7 OS.
I've made several assumptions, some of which may be totally off. Being that the case, I'm all ears.
Before anyone starts asking why I'm doing this I must be frank..
Stack Memory in Java is used for static memory allocation and the execution of a thread. It contains primitive values that are specific to a method and references to objects referred from the method that are in a heap. Access to this memory is in Last-In-First-Out (LIFO) order.
Heap memory is used by all the parts of the application whereas stack memory is used only by one thread of execution. Whenever an object is created, it's always stored in the Heap space and stack memory contains the reference to it.
There are two kinds of memory used in Java. These are called stack memory and heap memory. Stack memory stores primitive types and the addresses of objects. The object values are stored in heap memory.
The Java Virtual Machine divides the memory into Stack and Heap Memory. For Java Virtual Machine, executing an application in its maximum potential can happen from stack and heap memory. Every time a new variable or object is declared, the memory allocates memory dedicated to such operations.
You need to include in the stack the instruction pointer (8 bytes) and there may be other context information which is saved even if you don't believe it would need to be. The alignment could be 16 bytes, 8 bytes like the heap is. e.g. it could reserve 8-bytes for the return value even if there isn't one.
Java isn't as suited to heavy use of recursion like many languages are. e.g. it doesn't do tail-call optimisation which in this case would cause your program to run forever. ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With