昨天有帶大家快速認(rèn)識(shí)了下Java虛擬機(jī),但你知道Java虛擬機(jī)的堆和棧嗎答倡?不清楚的小伙伴就快來(lái)看下吧轰传!
堆中分配的是對(duì)象,也就是new出來(lái)的東西苇羡;棧中分配的是基本類(lèi)型和自定義對(duì)象的引用绸吸。簡(jiǎn)單來(lái)理解呢鼻弧,堆是用來(lái)存放對(duì)象的设江,棧是用來(lái)運(yùn)行程序的。
關(guān)于運(yùn)行數(shù)據(jù)區(qū)的堆
堆是在運(yùn)行數(shù)據(jù)區(qū)劃分出來(lái)的一塊內(nèi)存區(qū)域攘轩,用于存儲(chǔ)在程序運(yùn)行過(guò)程中創(chuàng)建的對(duì)象實(shí)例和數(shù)組叉存,在虛擬機(jī)運(yùn)行的所有線程創(chuàng)建的對(duì)象實(shí)例和數(shù)組都共享一個(gè)堆。
堆中的存儲(chǔ)空間是有限的度帮,當(dāng)堆中存儲(chǔ)的對(duì)象實(shí)例超過(guò)堆的存儲(chǔ)空間時(shí)歼捏,堆就無(wú)法再存儲(chǔ)新的實(shí)例對(duì)象,在這種情況下就會(huì)造成堆的溢出笨篷,java程序也會(huì)拋出內(nèi)存溢出異常瞳秽。因此當(dāng)堆中的實(shí)例對(duì)象不再需要時(shí),應(yīng)及時(shí)回收空間率翅,回收的空間再分配給新的實(shí)例對(duì)象练俐。
那么,在什么情況下要對(duì)堆中的實(shí)例對(duì)象進(jìn)行回收呢冕臭?開(kāi)發(fā)者可以使用new運(yùn)算符在堆中創(chuàng)建實(shí)例對(duì)象腺晾,但不能釋放已創(chuàng)建的實(shí)例對(duì)象。其實(shí)開(kāi)發(fā)者不需要考慮如何回收實(shí)例對(duì)象占用的存儲(chǔ)空間辜贵,虛擬機(jī)的垃圾收集器(垃圾收集器在后面的課程會(huì)講到)會(huì)自動(dòng)回收不再被運(yùn)行的程序引用的對(duì)象所占用的存儲(chǔ)空間悯蝉。
關(guān)于運(yùn)行數(shù)據(jù)區(qū)的棧
棧是一個(gè)數(shù)據(jù)結(jié)構(gòu),棧結(jié)構(gòu)是一種特殊的線性表托慨,限定僅在表的一端進(jìn)行元素的插入和刪除鼻由。當(dāng)表中沒(méi)有元素時(shí),稱(chēng)為空棧。若給定棧:
S = (a1嗡靡,a2跺撼,……,an)
則稱(chēng)a1是棧底元素讨彼,an是棧頂元素歉井,表中元素按a1,a2哈误,……哩至,an的次序進(jìn)棧,出棧的順序是an蜜自,……菩貌,a2,a1重荠。也就是說(shuō)箭阶,棧結(jié)構(gòu)的元素訪問(wèn)原則是后進(jìn)先出,也稱(chēng)為后進(jìn)先出的線性表的戈鲁,如下圖所示:
棧也是在運(yùn)行數(shù)據(jù)區(qū)劃分出來(lái)的一塊內(nèi)存區(qū)域仇参,棧是和線程相關(guān)的,虛擬機(jī)會(huì)為每個(gè)線程分配一個(gè)棧婆殿,棧以幀為單位保存線程的運(yùn)行狀態(tài)诈乒,一個(gè)棧幀保存了Java方法的參數(shù)、局部變量婆芦、中間運(yùn)算結(jié)果怕磨、返回值等數(shù)據(jù)。棧幀由局部變量區(qū)消约、操作數(shù)棧和棧數(shù)據(jù)區(qū)構(gòu)成肠鲫。當(dāng)線程調(diào)用一個(gè)Java方法時(shí),虛擬機(jī)會(huì)從方法所在的類(lèi)信息中得知此方法的局部變量區(qū)和操作數(shù)棧的大小或粮,并給棧幀分配內(nèi)存导饲,將棧幀壓入棧中。
每當(dāng)線程調(diào)用一個(gè)方法時(shí)被啼,虛擬機(jī)都會(huì)在該線程的棧中壓入一個(gè)棧幀帜消,這個(gè)棧幀為當(dāng)前棧幀。Java方法有兩種返回方式:一種是方法運(yùn)行完成后浓体,以return方式返回泡挺;一種是在方法運(yùn)行過(guò)程中,發(fā)生錯(cuò)誤拋出異常命浴,非正常返回娄猫。不管以哪種方式返回贱除,虛擬機(jī)都會(huì)將當(dāng)前棧幀彈出并釋放掉,這樣上一個(gè)方法的棧幀就成為當(dāng)前棧幀了媳溺。
堆和棧的關(guān)系
堆是存儲(chǔ)實(shí)例對(duì)象和數(shù)組的內(nèi)存區(qū)域月幌,棧是存儲(chǔ)線程內(nèi)類(lèi)方法運(yùn)行狀態(tài)的內(nèi)存區(qū)域。當(dāng)線程調(diào)用類(lèi)方法時(shí)悬蔽,與方法有關(guān)的類(lèi)變量和方法內(nèi)部的局部變量都會(huì)存儲(chǔ)到棧幀扯躺,當(dāng)這些類(lèi)變量和局部變量是對(duì)象引用變量時(shí),這些變量會(huì)指向堆中的實(shí)例對(duì)象或數(shù)組蝎困,方法執(zhí)行完成后录语,與方法相關(guān)的棧幀被彈出棧,棧幀占用的存儲(chǔ)空間被釋放禾乘,但堆中的實(shí)例對(duì)象或數(shù)組并沒(méi)有釋放澎埠,它們由垃圾收集器在隨后的時(shí)間進(jìn)行釋放。
好了始藕,以上就是給大家分享的關(guān)于Java虛擬機(jī)的堆和棧的解答了蒲稳,希望能給大家?guī)?lái)一定的幫助!
有問(wèn)題可以在下方評(píng)論區(qū)討論或者找我私聊哦~