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

Java(JVM)如何为每个线程分配堆栈,java,memory,jvm,Java,Memory,Jvm,Java应用程序启动时,所有线程都有一个堆。每个线程都有自己的堆栈 当Java应用程序启动时,我们使用JVM选项-Xms和-Xmx控制堆的大小,并使用-Xss控制堆栈大小 我的理解是,正在创建的堆成为JVM的“托管”内存,所有正在创建的对象都放在那里 但是堆栈创建是如何工作的呢?Java在创建每个线程时是否为其创建堆栈?如果是,堆栈在内存中的确切位置是什么?它肯定不在“托管”堆中 JVM是从本机内存创建堆栈,还是为堆栈预先分配一部分托管内存区域?如果是这样,JVM如何知道如何创建线程 JVM使用

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

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

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

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

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

JVM使用的内存不仅仅是堆。比如Java方法, 线程堆栈和本机句柄分别在内存中分配 堆以及JVM内部数据结构

因此,要回答您的问题:

Java在创建每个线程时是否为其创建堆栈

如果是,堆栈在内存中的确切位置是什么

在JVM分配的内存中,但不在堆上

如果是这样,JVM如何知道如何创建线程

没有

您可以创建任意数量的JVM,直到您的JVM内存达到最大值,并且

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


上面提到的都是JVM,尽管我发现很难相信其他JVM在这些基本问题上会有不同。

关于线程堆栈,有几件事可以告诉我们。除其他外:

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

  • 由于Java虚拟机堆栈除了用于推送和弹出帧之外从不直接操作,因此帧可能是堆分配的。Java虚拟机堆栈的内存不需要是连续的

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

现在,如果我们关注热点等JVM实现,我们可以获得更多信息。以下是我从不同来源收集的一些事实:

  • 热点中线程的最小堆栈大小似乎是固定的。这就是前面提到的
    -Xss
    选项的用途。
在JavaSE6中,Sparc上的默认值在32位VM中为512k,在64位VM中为1024k。。。您可以通过使用-Xss选项来减少堆栈大小。。。 64k是每个线程允许的最小堆栈空间量

  • JRockit将内存与堆栈所在的堆分开分配
请注意,JVM使用的内存不仅仅是堆。例如,Java方法、线程堆栈和本机句柄在内存中与堆以及JVM内部数据结构分开分配

  • HotSpot中的Java线程和本机OS线程之间存在直接映射

  • 但是HotSpot中的Java线程堆栈是由软件管理的,它不是OS本机线程堆栈

它使用一个单独的软件堆栈来传递Java参数,而本机C堆栈由VM本身使用。许多JVM内部变量(如Java线程的程序计数器或堆栈指针)存储在C变量中,这些变量不能保证总是保存在硬件寄存器中。这些软件解释器结构的管理消耗了相当大的总执行时间

  • JVM还将相同的Java线程堆栈用于本机方法和JVM运行时调用(例如类加载)

  • 有趣的是,作为性能优化,即使是分配的对象有时也可能位于堆栈上,而不是堆上

JVM可以使用一种称为转义分析(escape analysis)的技术,通过这种技术,JVM可以判断某些对象在其整个生命周期内都被限制在单个线程中,并且生命周期受给定堆栈帧的生命周期的限制。这样的对象可以在堆栈而不是堆上安全地分配

因为一个图像胜过千言万语,这里有一个


现在回答您的一些问题:

JVM如何知道如何创建线程

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

Java在创建每个线程时是否为其创建堆栈

如前所述,每个Java虚拟机线程都有一个私有Java虚拟机堆栈,与线程同时创建

如果是,堆栈在内存中的确切位置是什么?它肯定不在“托管”堆中

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

JVM是从本机内存创建堆栈,还是为堆栈预先分配一部分托管内存区域


堆栈是JVM管理的,因为Java规范规定了它的行为:Java虚拟机堆栈存储帧(§2.6)。Java虚拟机堆栈类似于传统语言的堆栈。一个例外是用于
本机
方法的本机方法堆栈。有关这方面的更多信息,请参见。

此外,虽然这些都是很好的答案,但这是JVM的内部规范。上述任何一项都可能随时发生变化。它不应该,也不应该,不管JVM如何工作。让JVM决定如何最好地管理它的资源。是的,但这并不意味着找出它是如何管理它的