今天來認識下Java虛擬機的堆和棧吧

昨天有帶大家快速認識了下Java虛擬機,但你知道Java虛擬機的堆和棧嗎?不清楚的小夥伴就快來看下吧!

堆中分配的是對象,也就是new出來的東西;棧中分配的是基本類型和自定義對象的引用。簡單來理解呢,堆是用來存放對象的,棧是用來運行程序的。


關於運行數據區的堆

堆是在運行數據區劃分出來的一塊內存區域,用於存儲在程序運行過程中創建的對象實例和數組,在虛擬機運行的所有線程創建的對象實例和數組都共享一個堆。

堆中的存儲空間是有限的,當堆中存儲的對象實例超過堆的存儲空間時,堆就無法再存儲新的實例對象,在這種情況下就會造成堆的溢出,java程序也會拋出內存溢出異常。因此當堆中的實例對象不再需要時,應及時回收空間,回收的空間再分配給新的實例對象。

那麼,在什麼情況下要對堆中的實例對象進行回收呢?開發者可以使用new運算符在堆中創建實例對象,但不能釋放已創建的實例對象。其實開發者不需要考慮如何回收實例對象佔用的存儲空間,虛擬機的垃圾收集器(垃圾收集器在後面的課程會講到)會自動回收不再被運行的程序引用的對象所佔用的存儲空間。


關於運行數據區的棧

棧是一個數據結構,棧結構是一種特殊的線性表,限定僅在表的一端進行元素的插入和刪除。當表中沒有元素時,稱為空棧。若給定棧:

S = (a1,a2,……,an)

則稱a1是棧底元素,an是棧頂元素,表中元素按a1,a2,……,an的次序進棧,出棧的順序是an,……,a2,a1。也就是說,棧結構的元素訪問原則是後進先出,也稱為後進先出的線性表的,如下圖所示:


Java |今天來認識下Java虛擬機的堆和棧吧

棧也是在運行數據區劃分出來的一塊內存區域,棧是和線程相關的,虛擬機會為每個線程分配一個棧,棧以幀為單位保存線程的運行狀態,一個棧幀保存了Java方法的參數、局部變量、中間運算結果、返回值等數據。棧幀由局部變量區、操作數棧和棧數據區構成。當線程調用一個Java方法時,虛擬機會從方法所在的類信息中得知此方法的局部變量區和操作數棧的大小,並給棧幀分配內存,將棧幀壓入棧中。

每當線程調用一個方法時,虛擬機都會在該線程的棧中壓入一個棧幀,這個棧幀為當前棧幀。Java方法有兩種返回方式:一種是方法運行完成後,以return方式返回;一種是在方法運行過程中,發生錯誤拋出異常,非正常返回。不管以哪種方式返回,虛擬機都會將當前棧幀彈出並釋放掉,這樣上一個方法的棧幀就成為當前棧幀了。


堆和棧的關係

堆是存儲實例對象和數組的內存區域,棧是存儲線程內類方法運行狀態的內存區域。當線程調用類方法時,與方法有關的類變量和方法內部的局部變量都會存儲到棧幀,當這些類變量和局部變量是對象引用變量時,這些變量會指向堆中的實例對象或數組,方法執行完成後,與方法相關的棧幀被彈出棧,棧幀佔用的存儲空間被釋放,但堆中的實例對象或數組並沒有釋放,它們由垃圾收集器在隨後的時間進行釋放。


Java |今天來認識下Java虛擬機的堆和棧吧


好了,以上就是給大家分享的關於Java虛擬機的堆和棧的解答了,希望能給大家帶來一定的幫助!

想領取全套架構資料的同學,幫忙轉發一下然後再關注我私信回覆“全套資料”得到獲取方式吧!


分享到:


相關文章: