Java中堆和棧的區(qū)別詳解
當(dāng)一個(gè)人開(kāi)始學(xué)習(xí)Java或者其他編程語(yǔ)言的時(shí)候,會(huì)接觸到堆和棧,由于一開(kāi)始沒(méi)有明確清晰的說(shuō)明解釋?zhuān)芏嗳藭?huì)產(chǎn)生很多疑問(wèn),什么是堆,什么是棧,堆和棧有什么區(qū)別?更糟糕的是,Java中存在棧這樣一個(gè)后進(jìn)先出(Last In First Out)的順序的數(shù)據(jù)結(jié)構(gòu),這就是java.util.Stack。這種情況下,不免讓很多人更加費(fèi)解前面的問(wèn)題。事實(shí)上,堆和棧都是內(nèi)存中的一部分,有著不同的作用,而且一個(gè)程序需要在這片區(qū)域上分配內(nèi)存。眾所周知,所有的Java程序都運(yùn)行在JVM虛擬機(jī)內(nèi)部,我們這里介紹的自然是JVM(虛擬)內(nèi)存中的堆和棧。
區(qū)別
java中堆和棧的區(qū)別自然是面試中的常見(jiàn)問(wèn)題,下面幾點(diǎn)就是其具體的區(qū)別
各司其職
最主要的區(qū)別就是棧內(nèi)存用來(lái)存儲(chǔ)局部變量和方法調(diào)用。
而堆內(nèi)存用來(lái)存儲(chǔ)Java中的對(duì)象。無(wú)論是成員變量,局部變量,還是類(lèi)變量,它們指向的對(duì)象都存儲(chǔ)在堆內(nèi)存中。
獨(dú)有還是共享
棧內(nèi)存歸屬于單個(gè)線(xiàn)程,每個(gè)線(xiàn)程都會(huì)有一個(gè)棧內(nèi)存,其存儲(chǔ)的變量只能在其所屬線(xiàn)程中可見(jiàn),即棧內(nèi)存可以理解成線(xiàn)程的私有內(nèi)存。
而堆內(nèi)存中的對(duì)象對(duì)所有線(xiàn)程可見(jiàn)。堆內(nèi)存中的對(duì)象可以被所有線(xiàn)程訪(fǎng)問(wèn)。
異常錯(cuò)誤
如果棧內(nèi)存沒(méi)有可用的空間存儲(chǔ)方法調(diào)用和局部變量,JVM會(huì)拋出java.lang.StackOverFlowError。
而如果是堆內(nèi)存沒(méi)有可用的空間存儲(chǔ)生成的對(duì)象,JVM會(huì)拋出java.lang.OutOfMemoryError。
空間大小
棧的內(nèi)存要遠(yuǎn)遠(yuǎn)小于堆內(nèi)存,如果你使用遞歸的話(huà),那么你的棧很快就會(huì)充滿(mǎn)。如果遞歸沒(méi)有及時(shí)跳出,很可能發(fā)生StackOverFlowError問(wèn)題。
你可以通過(guò)-Xss選項(xiàng)設(shè)置棧內(nèi)存的大小。-Xms選項(xiàng)可以設(shè)置堆的開(kāi)始時(shí)的大小,-Xmx選項(xiàng)可以設(shè)置堆的最大值。
這就是Java中堆和棧的區(qū)別。理解好這個(gè)問(wèn)題的話(huà),可以對(duì)你解決開(kāi)發(fā)中的問(wèn)題,分析堆內(nèi)存和棧內(nèi)存使用,甚至性能調(diào)優(yōu)都有幫助。
查看默認(rèn)值(Updated)
查看堆的默認(rèn)值,使用下面的代碼,其中InitialHeapSize為最開(kāi)始的堆的大小,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)
查看棧的默認(rèn)值,其中ThreadStackSize為棧內(nèi)存的大小。
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.
譯文在原文基礎(chǔ)上進(jìn)行了修改,整理,刪減。如有興趣可以訪(fǎng)問(wèn)原文。P.S.地址已被墻。
相關(guān)文章
Java內(nèi)存溢出的幾個(gè)區(qū)域總結(jié)(注意避坑!)
內(nèi)存溢出是指應(yīng)用系統(tǒng)中存在無(wú)法回收的內(nèi)存或使用的內(nèi)存過(guò)多,最終使得程序運(yùn)行要用到的內(nèi)存大于虛擬機(jī)能提供的最大內(nèi)存,下面這篇文章主要給大家介紹了關(guān)于Java內(nèi)存溢出的幾個(gè)區(qū)域,總結(jié)出來(lái)給大家提醒注意避坑,需要的朋友可以參考下2022-11-11Java使用@Autowired注解獲取對(duì)象為null的幾種情況及解決方法
這篇文章主要給大家介紹了使用@Autowired注解獲取對(duì)象為null的幾種情況以及?解決方法,文中有詳細(xì)的代碼示例講解,具有一定的參考價(jià)值,需要的朋友可以參考下2023-09-09詳解Java編程規(guī)約(命名風(fēng)格、常量定義、代碼格式)
這篇文章主要介紹了詳解Java編程規(guī)約(命名風(fēng)格、常量定義、代碼格式),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-10-10java實(shí)現(xiàn)手寫(xiě)一個(gè)簡(jiǎn)單版的線(xiàn)程池
有些人可能對(duì)線(xiàn)程池比較陌生,并且更不熟悉線(xiàn)程池的工作原理。本文就來(lái)手寫(xiě)一個(gè)簡(jiǎn)單版的線(xiàn)程池,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08Java通過(guò)工廠、Map容器創(chuàng)建對(duì)象的方法
這篇文章主要介紹了Java通過(guò)工廠、Map容器創(chuàng)建對(duì)象的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03Java數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)之樹(shù)
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)之樹(shù),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java數(shù)據(jù)結(jié)構(gòu)的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-05-05Spring五大類(lèi)注解讀取存儲(chǔ)Bean對(duì)象的方法
這篇文章主要介紹了Spring五大類(lèi)注解讀取存儲(chǔ)Bean對(duì)象,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09java生成csv文件亂碼的解決方法示例 java導(dǎo)出csv亂碼
這篇文章主要介紹了java生成csv文件亂碼的解決方法,大家可以直接看下面的示例2014-01-01SpringBoot接收與響應(yīng)xml報(bào)文請(qǐng)求的實(shí)現(xiàn)
我們?cè)谶M(jìn)行接口對(duì)接時(shí),會(huì)出現(xiàn)報(bào)文形式的信息傳遞,這篇文章主要給大家介紹了關(guān)于SpringBoot接收與響應(yīng)xml報(bào)文請(qǐng)求的相關(guān)資料,需要的朋友可以參考下2023-06-06