Java(JVM)如何为每个线程分配栈
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36898701/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does Java (JVM) allocate stack for each thread
提问by Kevin
A Java application starts up with one heap for all threads. Each thread has its own stack.
Java 应用程序启动时所有线程都使用一个堆。每个线程都有自己的堆栈。
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.
当Java应用程序启动时,我们使用JVM选项-Xms
和-Xmx
控制堆的大小和-Xss
控制堆栈大小。
My understanding is that the heap being created becomes a "managed" memory of JVM and all the object being created are placed there.
我的理解是,正在创建的堆成为 JVM 的“托管”内存,并且所有正在创建的对象都放置在那里。
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.
但是堆栈创建是如何工作的呢?Java 是否在创建时为每个线程创建一个堆栈?如果是这样,堆栈在内存中的确切位置?它当然不在“托管”堆中。
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?
JVM 是从本机内存创建堆栈还是为堆栈预先分配一部分托管内存区域?如果是这样,JVM 如何知道将如何创建线程?
回答by Daniel
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.
JVM 使用的内存不仅仅是堆。例如,Java 方法、线程堆栈和本机句柄在与堆以及 JVM 内部数据结构分开的内存中分配。
So to answer your questions:
所以回答你的问题:
Does Java create a stack for each thread when it is created?
Java 是否在创建时为每个线程创建一个堆栈?
Yes.
是的。
If so, where exactly the stack is on the memory?
如果是这样,堆栈在内存中的确切位置?
In the JVM allocated memory, but not on the heap.
在JVM中分配了内存,但不在堆上。
If so, how does JVM knows how may threads will be created?
如果是这样,JVM 如何知道将如何创建线程?
It doesn't.
它没有。
You can create as many as you'd like until you've maxed out your JVM memory and get
您可以创建任意数量的对象,直到您的 JVM 内存达到最大值并获得
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
EDIT:
编辑:
All of the above refers to JrockitJVM, although i find it hard to believe other JVMs would be different on such fundamental issues.
以上所有内容均指JrockitJVM,尽管我发现很难相信其他 JVM 在这些基本问题上会有所不同。
回答by Mifeet
There are a few things about thread stacks that the Java specificationtells us. Among other things:
Java 规范告诉我们一些关于线程堆栈的事情。除其他事项外:
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.
每个 Java 虚拟机线程都有一个私有的 Java 虚拟机堆栈,与线程同时创建。
因为除了推送和弹出帧之外,Java 虚拟机堆栈从不直接操作,所以帧可能被分配到堆上。Java 虚拟机堆栈的内存不需要是连续的。
规范允许 Java 虚拟机堆栈具有固定大小或根据计算需要动态扩展和收缩。
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:
现在,如果我们专注于 HotSpot 等 JVM 实现,我们可以获得更多信息。以下是我从不同来源收集的一些事实:
- The minimum stack size in HotSpot for a thread seems to be fixed. This is what the aforementioned
-Xss
option is for. (Source)
- HotSpot 中线程的最小堆栈大小似乎是固定的。这就是上述
-Xss
选项的用途。 (来源)
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.
在 Java SE 6 中,Sparc 上的默认值在 32 位 VM 中为 512k,在 64 位 VM 中为 1024k。...您可以通过运行 -Xss 选项来减少堆栈大小。... 64k 是每个线程允许的最小堆栈空间量。
- JRockit allocates memory separate from the heap where stacks are located. (Source)
- JRockit 分配与堆栈所在的堆分开的内存。(来源)
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.
请注意,JVM 使用的内存不仅仅是堆。例如,Java 方法、线程堆栈和本机句柄在与堆以及 JVM 内部数据结构分开的内存中分配。
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.
它使用单独的软件堆栈来传递 Java 参数,而本地 C 堆栈由 VM 本身使用。许多 JVM 内部变量,例如程序计数器或 Java 线程的堆栈指针,都存储在 C 变量中,并不能保证始终保存在硬件寄存器中。这些软件解释器结构的管理消耗了总执行时间的很大一部分。
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.
JVM 可以使用一种称为逃逸分析的技术,通过该技术,它们可以判断某些对象在其整个生命周期内都保持局限于单个线程,并且该生命周期受给定堆栈帧的生命周期的限制。这样的对象可以安全地分配在堆栈上而不是堆上。
And because an image is worth a thousand words, here is one from James Bloom
因为一张图片值一千个字,这里是James Bloom 的一个
Now answering some of your questions:
现在回答你的一些问题:
How does JVM knows how may threads will be created?
JVM 如何知道将如何创建线程?
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 threadsand 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?
Java 是否在创建时为每个线程创建一个堆栈?
As mentioned earlier, each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.(Source).
如前所述,每个 Java 虚拟机线程都有一个私有的 Java 虚拟机堆栈,与线程同时创建。(来源)。
If so, where exactly the stack is on the memory? It is certainly not in the "managed" heap.
如果是这样,堆栈在内存中的确切位置?它当然不在“托管”堆中。
As stated above, Java specificationallows stack memory to be stored on heap, technically speaking. But at least JRockit JVM uses a different part of memory.
如上所述,从技术上讲,Java 规范允许将堆栈内存存储在堆上。但至少 JRockit JVM 使用了不同的内存部分。
Does JVM create stack from native memory or does it pre-allocate a section of managed memory area for stack?
JVM 是从本机内存创建堆栈还是为堆栈预先分配一部分托管内存区域?
The stack is JVM managed because the Java specification prescribeshow 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.
堆栈是由 JVM 管理的,因为 Java 规范规定了它的行为方式:Java 虚拟机堆栈存储帧(第 2.6 节)。Java 虚拟机堆栈类似于传统语言的堆栈。一种例外是用于native
方法的本机方法堆栈。在规范中再次详细介绍了这一点。