java - Java(JVM)如何为每个线程分配堆栈

标签 java memory jvm

Java 应用程序启动时所有线程都有一个堆。每个线程都有自己的堆栈。

当一个Java应用程序启动时,我们使用JVM选项-Xms-Xmx来控制堆的大小和-Xss控制堆栈大小。

我的理解是,正在创建的堆成为 JVM 的“托管”内存,并且所有正在创建的对象都放置在那里。

但是堆栈创建是如何工作的? Java在创建每个线程时是否为每个线程创建一个堆栈?如果是这样,堆栈在内存中的确切位置?它肯定不在“托管”堆中。

JVM 是从 native 内存创建堆栈还是为堆栈预先分配一部分托管内存区域?如果是这样,JVM如何知道线程将如何创建?

最佳答案

Java specification 有一些关于线程堆栈的事情。告诉我们。除其他事项外:

  • 每个 Java 虚拟机线程都有一个私有(private)的 Java 虚拟机堆栈,与线程同时创建。

  • 因为除了推送和弹出帧外,Java 虚拟机堆栈永远不会被直接操作,因此帧可能是堆分配的。 Java 虚拟机堆栈的内存不需要是连续的。

  • 规范允许 Java 虚拟机堆栈具有固定大小或根据计算需要动态扩展和收缩。

现在,如果我们专注于诸如 HotSpot 之类的 JVM 实现,我们可以获得更多信息。以下是我从不同来源收集的一些事实:

  • HotSpot 中线程的最小堆栈大小似乎是固定的。这就是前面提到的 -Xss 选项的用途。 (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 分配与堆栈所在的堆分开的内存。 (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.

  • 在 HotSpot 中,Java 线程和本地操作系统线程之间存在直接映射关系。 (Source) .

  • 但 HotSpot 中的 Java 线程堆栈是软件管理的,它不是 OS 原生线程堆栈。 (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 还为本地方法和 JVM 运行时调用(例如类加载)使用相同的 Java 线程堆栈。 (Source) .

  • 有趣的是,即使分配的对象有时也可能位于堆栈而不是堆上,以作为性能优化。 (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.

因为一张图片值一千字,这里有一张来自 James Bloom Java memory


现在回答您的一些问题:

How does JVM knows how may threads will be created?

它没有。通过创建可变数量的线程可以很容易地通过矛盾证明。它确实对最大线程数和每个线程的堆栈大小做出了一些假设。这就是为什么如果分配太多线程可能会耗尽内存(不是堆内存!)。

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

如前所述,每个 Java 虚拟机线程都有一个私有(private)的 Java 虚拟机堆栈,与线程同时创建。 (Source) .

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

如上所述,Java specification从技术上讲,允许堆栈内存存储在堆上。但至少 JRockit JVM 使用了不同的内存部分。

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

堆栈由 JVM 管理,因为 Java 规范 prescribes它必须如何表现:Java 虚拟机堆栈存储帧(第 2.6 节)。 Java 虚拟机堆栈类似于传统语言的堆栈。一个异常(exception)是用于 native 方法的 Native Method 堆栈。在 the specification 中再次了解更多信息.

关于java - Java(JVM)如何为每个线程分配堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36898701/

相关文章:

java - 通过 JNI NewObject 创建实例时 jvm.dll 中出现异常 0xC0000005

java - 在 Windows 机器上托管 java 网站

c++ - 如何将数组指向嵌入式系统上的某个特定内存地址

Java 删除一个迭代器,该迭代器删除同一列表中的另一个元素

java - Apache AsyncHttpClient 4.1.4 创建新的套接字连接而不是重用来自连接池的连接

c++ - 为什么访问一个变量的地址会改变另一个变量的地址?

C malloc/free corruption 一般问题

Java:为什么不使用 XX:SurvivorRatio 的默认值?

scala - Scala 为 JVM 1.7 生成字节码的优势

java - 在 HP Load Runner 的 VuGen 中加载 javai.dll 时出错