Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inferring a method's stack memory use in Java

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..

like image 544
devoured elysium Avatar asked Feb 24 '12 14:02

devoured elysium


People also ask

What is the use of stack memory in Java?

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.

What is Java heap stack memory?

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.

What are types of memories used in Java?

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.

How is memory allocated in Java?

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.


1 Answers

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. ;)

like image 81
Peter Lawrey Avatar answered Oct 11 '22 12:10

Peter Lawrey