How does Java (JVM) allocate stack for each thread

2019-01-12 18:41发布

问题:

A Java application starts up with one heap for all threads. Each thread has its own stack.

When a Java application is started, we use the JVM option -Xms and -Xmx to control the size of heap and -Xss to control the stack size.

My understanding is that the heap being created becomes a "managed" memory of JVM and all the object being created are placed there.

But how does the stack creation work? Does Java create a stack for each thread when it is created? If so, where exactly the stack is on the memory? It is certainly not in the "managed" heap.

Does JVM create stack from native memory or does it pre-allocate a section of managed memory area for stack? If so, how does JVM know how may threads will be created?

回答1:

There are a few things about thread stacks that the Java specification tells us. Among other things:

  • Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.

  • Because the Java Virtual Machine stack is never manipulated directly except to push and pop frames, frames may be heap allocated. The memory for a Java Virtual Machine stack does not need to be contiguous.

  • Specification permits Java Virtual Machine stacks either to be of a fixed size or to dynamically expand and contract as required by the computation.

Now, if we focus on JVM implementations such as HotSpot, we can get some more information. Here are a few facts I've collected from different sources:

  • The minimum stack size in HotSpot for a thread seems to be fixed. This is what the aforementioned -Xss option is for. (Source)

In Java SE 6, the default on Sparc is 512k in the 32-bit VM, and 1024k in the 64-bit VM. ... You can reduce your stack size by running with the -Xss option. ... 64k is the least amount of stack space allowed per thread.

  • JRockit allocates memory separate from the heap where stacks are located. (Source)

Note that the JVM uses more memory than just the heap. For example Java methods, thread stacks and native handles are allocated in memory separate from the heap, as well as JVM internal data structures.

  • There is a direct mapping between a Java Thread and a native OS Thread in HotSpot. (Source).

  • But the Java thread stack in HotSpot is software managed, it is not an OS native thread stack. (Source)

It uses a separate software stack to pass Java arguments, while the native C stack is used by the VM itself. A number of JVM internal variables, such as the program counter or the stack pointer for a Java thread, are stored in C variables, which are not guaranteed to be always kept in the hardware registers. Management of these software interpreter structures consumes a considerable share of total execution time.

  • JVM also utilizes the same Java thread stack for the native methods and JVM runtime calls (e.g. class loading). (Source).

  • Interestingly, even allocated objects may be sometimes located on stack instead on heap as a performance optimization. (Source)

JVMs can use a technique called escape analysis, by which they can tell that certain objects remain confined to a single thread for their entire lifetime, and that lifetime is bounded by the lifetime of a given stack frame. Such objects can be safely allocated on the stack instead of the heap.

And because an image is worth a thousand words, here is one from James Bloom


Now answering some of your questions:

How does JVM knows how may threads will be created?

It doesn't. Can be easily proved by contradiction by creating a variable number of threads. It does make some assumptions about the maximum number of threads and stack size of each thread. That's why you may run out of memory (not meaning heap memory!) if you allocate too many threads.

Does Java create a stack for each thread when it is created?

As mentioned earlier, each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. (Source).

If so, where exactly the stack is on the memory? It is certainly not in the "managed" heap.

As stated above, Java specification allows stack memory to be stored on heap, technically speaking. But at least JRockit JVM uses a different part of memory.

Does JVM create stack from native memory or does it pre-allocate a section of managed memory area for stack?

The stack is JVM managed because the Java specification prescribes how it must behave: A Java Virtual Machine stack stores frames (§2.6). A Java Virtual Machine stack is analogous to the stack of a conventional language. One exception are Native Method stacks used for native methods. More about this again in the specification.



回答2:

JVM uses more memory than just the heap. For example Java methods, thread stacks and native handles are allocated in memory separate from the heap, as well as JVM internal data structures.

Further reading.

So to answer your questions:

Does Java create a stack for each thread when it is created?

Yes.

If so, where exactly the stack is on the memory?

In the JVM allocated memory, but not on the heap.

If so, how does JVM knows how may threads will be created?

It doesn't.

You can create as many as you'd like until you've maxed out your JVM memory and get

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

EDIT:

All of the above refers to Jrockit JVM, although i find it hard to believe other JVMs would be different on such fundamental issues.



标签: java memory jvm