2013-10-17 112 views
5

當我這樣說:創建線程對象在哪裏?堆棧還是堆?

Thread t1 = new Thread(); 

它在堆或堆棧創建它?

+0

「可見」部分位於JVM堆中。對於正在運行的線程,至少還有一個在別處分配的特定於操作系統的部分,但它都是自動處理的。 –

回答

7
Thread t1 = new Thread(); 

這在堆中分配對象,即t1。

隨着每個新線程的出現,它都有自己的pc寄存器(程序計數器)和Java堆棧。如果線程正在執行Java方法(不是本地方法),則pc寄存器的值指示要執行的下一條指令。線程的Java堆棧存儲線程的Java(非本地)方法調用狀態。 Java方法調用的狀態包括its local variables, the parameters with which it was invoked, its return value(如果有),and intermediate calculations。本機方法調用的狀態以實現相關的方式存儲在本機方法堆棧中,以及可能存儲在寄存器或其他實現相關內存區域中。

Java堆棧由堆棧幀(或幀)組成。堆棧框架包含一個Java方法調用的狀態。當一個線程調用一個方法時,Java虛擬機會將一個新的框架推送到該線程的Java堆棧中。該方法完成後,虛擬機將彈出並放棄該方法的框架。

Java虛擬機沒有寄存器來保存中間數據值。指令集使用Java堆棧來存儲中間數據值。

該圖顯示了執行三個線程的虛擬機實例的快照。在快照的瞬間,線程1和2正在執行Java方法。線程三正在執行一個本地方法。它還顯示了Java虛擬機爲每個線程創建的內存區域,這些區域對於擁有的線程是私有的。沒有線程可以訪問另一個線程的pc寄存器或Java堆棧。

enter image description here

+0

謝謝@Trying!但是可以解釋一下線程的本地方法是什麼?和這種說法 - 「本地方法調用的狀態以實現相關的方式存儲在本地方法堆棧中,以及可能存儲在寄存器或其他實現相關的存儲區中。」 – Chiran

+1

如果一個線程執行一些本地操作,jni的東西。對於另一個問題,這意味着diff os在線程和空間分配方面有不同的實現。 – Trying

+0

嗨,請說明本機是否包含OS級API調用?就像調用Java I/O中的read(),write()方法一樣。 –

10

沒有辦法在Java堆棧中分配對象。
堆棧只能保存引用和原語,並且只能用於局部變量。

請注意,啓動一個線程將爲該線程創建一個新的堆棧。

+2

+1更具體地說,'Thread'對象及其字段分配在堆上。與新線程關聯的堆棧內存由JVM/OS分配,但在堆上不是_not_。它被分配在不同的內存部分。 – Gray

+0

您不能在堆棧上顯式分配對象,但JVM可以在堆棧上將對象分配爲優化,只要它們足夠小並且不會轉義當前線程。請參閱本文「堆棧分配」一節:http://www.ibm.com/developerworks/java/library/j-jtp09275/index.html – dcernahoschi

+0

注意:Java 7/8允許將對象放置在堆棧上。 –

2

在Java 8,使用逃逸分析的對象可以在棧上創建。當檢測到一個對象沒有轉義當前方法時(在執行內聯操作之後),會發生這種情況。注意:這種優化在Java 7中可用,但我認爲它不會奏效。

但是,只要您致電start()它將逃脫當前的方法,因此它必須放在堆上。

當我這樣說:

Thread t1 = new Thread(); 

它在堆或堆棧創建它?

它可以把它放在堆棧上,前提是你不用它來創建一個真正的線程。即如果你這樣

Thread t1 = new Thread(runnable); 
t1.start(); 

它必須把它放在堆上。