1. 程式人生 > >對堆、棧在不同場景的理解

對堆、棧在不同場景的理解

最近學Java的時候,在書中經常看到某部分儲存到什麼地方,記憶體是怎麼分配的以及堆疊等問題;然後,想起以前學資料結構的時候,記憶體中也學到了資料的儲存,講到了堆和棧,作業系統中,也是有堆和棧這個概念的,這個確實讓我非常混淆,今天好好整理下,也參考了很多資料,總結下,這個堆疊在各個情況下的理解。

1. JVM就是基於堆疊的虛擬機器,JVM為每個新建立的執行緒都分配了一個堆疊,對於一個java程式而言,它的執行就是通過堆疊的操作來完成的。在Java中,記憶體分為堆記憶體和棧記憶體。在函式中定義的一些基本型別的變數和物件的引用變數都是在函式的棧記憶體中分配;而由new建立的物件和陣列存放於堆記憶體中。在棧記憶體中,java為變數分配記憶體空間,同時java也會自動釋放掉為該變數分配的記憶體空間,在對記憶體中,java虛擬機器自動垃圾回收器來管理堆中分配的記憶體。棧有一個很重要的特殊性,就是存在棧中的資料可以共享。比如我們同時定義:int a=3; int b=3;編譯器先處理int a =3;首先它會在棧中建立一個變數為a的引用,然後查詢棧中是否有3這個值,如果沒有找到,就將3存放進來,然後a指向3;接著處理int b=3,在建立b的引用變數後,因為棧中已經有3這個值了,便將b直接指向3。這樣,就出現了a和b同時都指向3的情況。這時,如果另a=4,那麼編譯器會重新搜尋棧中是否有4,如果沒有,則將4存進來,並令a指向4,如果有了,則將a指向這個地址。因此a的值改變不會影響到b的值,要注意這種資料的共享與兩個物件的引用同時指向一個物件的這種共享是不同的。因為這種情況a的修改並不會影響到b,這是編譯器完成的。在堆中,存放的物件,其實,我麼Book novel=new Book()的時候,其中novel這個引用變數時存放在棧記憶體中的,然後指向物件在堆中的地址。為什麼在堆中存放物件或者陣列,這是因為物件和陣列所需的儲存空間只有在執行時建立了物件之後才能確定的,堆具有這種靈活性。同時,堆是由垃圾回收來負責的,它的優勢就是可以動態的分配記憶體的大小,生存期也不必事先告訴編譯器。棧的優勢就是存取速度快,僅次於暫存器,棧資料可以共享。存在棧中的資料大小與生存期必須是確定的,所以存放一些基本的資料型別。

2、在C/C++中,與在作業系統中一樣,棧區是由編譯器自動分配和釋放的,存放函式的引數值、區域性變數的值等。其操作方法類似於資料結構中的棧,先進後出;堆區一般由程式設計師分配和釋放,若程式設計師不釋放,程式結束時可能由作業系統回收。這裡的堆與資料結構的堆又是不一樣的,這裡的堆類似於連結串列。3、在資料結構中,棧就是一種先進後出,後進先出的資料結構,和佇列是相反的;而堆通常是一個可以被看做一棵樹的陣列物件。堆總是一棵完全樹,即除了最底層,其它層的結點都被元素填滿,根結點最大的堆叫做最大堆或者大根堆。