當一個人開始學習Java或其他程式語言的時候,會接觸到堆和棧,由於一開始沒有明確清晰的說明解釋,很多人會產生很多疑問,什麼是堆,什麼是棧,堆和棧有什麼區別?更糟的是,Java中存在堆疊這樣一個後進先出(Last In First Out)的順序的資料結構,這就是java.util.Stack。這種情況下,不免讓很多人更費解前面的問題。事實上,堆和棧都是記憶體中的一部分,有著不同的作用,而且一個程式需要在這片區域上分配記憶體。眾所周知,所有的Java程式都運行在JVM虛擬機器內部,我們這裡介紹的自然是JVM(虛擬)記憶體中的堆疊和堆疊。
差別
java中堆疊和堆疊的區別自然是面試中的常見問題,下面幾點就是其具體的區別
各司其職
最主要的差別就是棧記憶體用來儲存局部變數和方法呼叫。
而堆記憶體用來儲存Java中的物件。無論是成員變量,局部變量,還是類別變量,它們指向的物件都儲存在堆記憶體中。
獨有還是共享
棧內存歸屬於單一線程,每個線程都會有一個棧內存,其儲存的變數只能在其所屬線程中可見,即棧內存可以理解成線程的私有內存。
而堆記憶體中的物件對所有線程可見。堆記憶體中的物件可以被所有執行緒存取。
異常錯誤
如果堆疊記憶體沒有可用的空間儲存方法呼叫和局部變量,JVM會拋出java.lang.StackOverFlowError。
而如果是堆記憶體沒有可用的空間儲存產生的對象,JVM會拋出java.lang.OutOfMemoryError。
空間大小
棧的內存要遠遠小於堆內存,如果你使用遞歸的話,那麼你的棧很快就會充滿。如果遞迴沒有及時跳出,很可能發生StackOverFlowError問題。
你可以透過-Xss選項設定棧記憶體的大小。 -Xms選項可以設定堆的開始時的大小,-Xmx選項可以設定堆的最大值。
這就是Java中堆和棧的差別。理解好這個問題的話,可以對你解決開發中的問題,分析堆疊記憶體和堆疊記憶體使用,甚至效能調優都有幫助。
查看預設值(Updated)
查看堆的預設值,使用下面的程式碼,其中InitialHeapSize為最開始的堆的大小,MaxHeapSize為堆的最大值。
複製代碼代碼如下:
13:17 $ java -XX:+PrintFlagsFinal -version | grep HeapSize
uintx ErgoHeapSizeLimit = 0 {product}
uintx HeapSizePerGCThread = 87241520 {product}
uintx InitialHeapSize := 134217728 {product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx MaxHeapSize := 2147483648 {product}
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
查看堆疊的預設值,其中ThreadStackSize為堆疊記憶體的大小。
複製代碼代碼如下:
13:21 $ java -XX:+PrintFlagsFinal -version | grep ThreadStackSize
intx CompilerThreadStackSize = 0 {pd product}
intx ThreadStackSize = 1024 {pd product}
intx VMThreadStackSize = 1024 {pd product}
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
譯文訊息
原汁原味的英文原文:http://javarevisited.blogspot.com.au/2013/01/difference-between-stack-and-heap-java.html.
譯文在原文基礎上進行了修改,整理,刪減。如有興趣可以訪問原文。 PS位址已被牆。