簡體   English   中英

Java(JVM)如何為每個線程分配堆棧

[英]How does Java (JVM) allocate stack for each thread

Java應用程序以所有線程的一個堆啟動。 每個線程都有自己的堆棧。

啟動Java應用程序時,我們使用JVM選項-Xms-Xmx來控制堆的大小,並使用-Xss來控制堆棧的大小。

我的理解是,正在創建的堆成為JVM的“托管”內存,所有正在創建的對象都放置在該處。

但是堆棧創建如何工作? Java是否在創建每個線程時都為其創建堆棧? 如果是這樣,堆棧到底在內存中的什么位置? 它肯定不在“托管”堆中。

JVM是從本機內存創建堆棧還是為堆棧預先分配了一部分托管內存區域? 如果是這樣,JVM如何知道如何創建線程?

Java規范告訴我們有關線程堆棧的一些信息。 除其他事項外:

  • 每個Java虛擬機線程都有一個私有Java虛擬機堆棧,與該線程同時創建。

  • 因為除了推送和彈出幀外,從不直接操縱Java虛擬機堆棧,所以可以為堆分配幀。 Java虛擬機堆棧的內存不必是連續的。

  • 規范允許Java虛擬機堆棧具有固定大小,或者根據計算要求動態擴展和收縮。

現在,如果我們專注於諸如HotSpot之類的JVM實現,我們可以獲得更多信息。 這是我從不同來源收集到的一些事實:

  • HotSpot中線程的最小堆棧大小似乎是固定的。 這就是前面提到的-Xss選項的作用。 (資源)

在Java SE 6中,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還對本地方法和JVM運行時調用(例如,類加載)使用相同的Java線程堆棧。 (來源)

  • 有趣的是,作為性能優化,甚至分配的對象有時也可能位於堆棧上,而不是堆上。 (資源)

JVM可以使用一種稱為轉義分析的技術,通過這種技術,他們可以告訴我們某些對象在其整個生命周期內都被限制在單個線程中,並且生命周期受給定堆棧幀的生命周期的限制。 這樣的對象可以安全地分配在堆棧上而不是堆上。

而且因為一張圖像值一千個字,所以這是詹姆斯·布魯姆James Bloom)的照片 Java內存


現在回答您的一些問題:

JVM如何知道如何創建線程?

沒有。 通過創建可變數量的線程可以很容易地通過矛盾證明。 它確實對最大線程數和每個線程的堆棧大小做了一些假設。 這就是為什么分配過多線程可能會耗盡內存(不是堆內存!)的原因。

Java是否在創建每個線程時都為其創建堆棧?

如前所述, 每個Java虛擬機線程都有一個私有Java虛擬機堆棧,與該線程同時創建。 (來源)

如果是這樣,堆棧到底在內存中的什么位置? 它肯定不在“托管”堆中。

如上所述,從技術上講, Java規范允許將堆棧內存存儲在堆上。 但是至少JRockit JVM使用內存的不同部分。

JVM是從本機內存創建堆棧還是為堆棧預先分配了一部分托管內存區域?

該堆棧受JVM管理,因為Java規范規定了它必須如何運行: Java虛擬機堆棧存儲幀(第2.6節)。 Java虛擬機堆棧類似於常規語言的堆棧 一種例外是用於native方法的native機方法堆棧。 規范中再次對此進行更多介紹。

JVM使用的內存不僅僅是堆。 例如,Java方法,線程堆棧和本機句柄與堆以及JVM內部數據結構分開分配在內存中。

進一步閱讀

因此,回答您的問題:

Java是否在創建每個線程時都為其創建堆棧?

是。

如果是這樣,堆棧到底在內存中的什么位置?

在JVM中分配了內存,但不在堆上。

如果是這樣,JVM如何知道將如何創建線程?

沒有。

您可以創建任意數量的文件,直到用完JVM內存並獲得

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

編輯:

以上所有內容都是針對Jrockit JVM的,盡管我很難相信其他JVM在此類基本問題上會有所不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM