1. 程式人生 > 其它 >JAVA中的棧和堆

JAVA中的棧和堆

JAVA在程式執行時,在記憶體中劃分5片空間進行資料的儲存。分別是:1:暫存器。2:本地方法區。3:方法區。4:棧。5:堆。

基本,棧stack和堆heap這兩個概念很重要,不瞭解清楚,後面就不用學了。

以下是這幾天棧和堆的學習記錄和心得。得些記錄下來。以後有學到新的,會慢慢補充。

一、先說一下最基本的要點

基本資料型別、區域性變數都是存放在棧記憶體中的,用完就消失。
new建立的例項化物件及陣列,是存放在堆記憶體中的,用完之後靠垃圾回收機制不定期自動消除。

二、先明確以上兩點,以下示例就比較好理解了


示例1

main()
  int x=1;
show ()
  int x=2

主函式main()中定義變數int x=1,show()函式中定義變數int x=1。最後show()函式執行完畢。


以上程式執行步驟:

第1步——main()函式是程式入口,JVM先執行,在棧記憶體中開闢一個空間,存放int型別變數x,同時附值1。
第2步——JVM執行show()函式,在棧記憶體中又開闢一個新的空間,存放int型別變數x,同時附值2。
     此時main空間與show空間並存,同時執行,互不影響。
第3步——show()執行完畢,變數x立即釋放,空間消失。但是main()函式空間仍存在,main中的變數x仍然存在,不受影響。

示意圖如下:

——————————————————————————————————————————————————————————————————————

示例2

main()
  int[] x=new int[3];
  x[0]=20

主函式main()中定義陣列x,元素型別int,元素個數3。

以上程式執行步驟
第1步——執行int[] x=new int[3];
  隱藏以下幾分支
  JVM執行main()函式,在棧記憶體中開闢一個空間,存放x變數(x變數是區域性變數)。
  同時,在堆記憶體中也開闢一個空間,存放new int[3]陣列,堆記憶體會自動記憶體首地址值,如0x0045。
  陣列在棧記憶體中的地址值,會附給x,這樣x也有地址值。所以,x就指向(引用)了這個陣列。此時,所有元素均未附值,但都有預設初始化值0。

第2步——執行x[0]=20
  即在堆記憶體中將20附給[0]這個陣列元素。這樣,陣列的三個元素值分別為20,0,0

示圖如下:

——————————————————————————————————————————————————————————————————————


示例3
main()
  int[] x=new int[3];
  x[0]=20
  x=null;

以上步驟執行步驟
第1、2步——與示例2完全一樣,略。

第3步——執行x=null;
  null表示空值,即x的引用陣列記憶體地址0x0045被刪除了,則不再指向棧記憶體中的陣列。此時,堆中的陣列不再被x使用了,即被視為垃圾,JVM會啟動垃圾回收機制,不定時自動刪除。

示圖如下

——————————————————————————————————————————————————————————————————

示例4
main()
  int[] x=new int[3];
  int[] y=x;
  y[1]=100
  x=null;

以上步驟執行步驟

第1步——與示例2第1步一致,略。
第2步——執行int[] y=x,
  在棧記憶體定義了新的陣列變數記憶體y,同時將x的值0x0045附給了y。所以,y也指向了堆記憶體中的同一個陣列。
第3步——執行y[1]=100
  即在堆記憶體中將20附給[0]這個陣列元素。這樣,陣列的三個元素值分別為0,100,0
第4步——執行x=null
  則變數x不再指向棧記憶體中的陣列了。但是,變數y仍然指向,所以陣列不消失。

示圖如下

——————————————————————————————————————————————————————————————————

示例5

Car c=new Car;
c.color="blue";
Car c1=new Car;
c1.num=5;

 雖然是個物件都引用new Car,但是是兩個不同的物件。每一次new,都產生不同的實體

——————————————————————————————————————————————————————————————————

示例6

Car c=new Car;
c.num=5;
Car c1=c;
c1.color="green";
c.run();

Car c1=c,這句話相當於將物件複製一份出來,兩個物件的記憶體地址值一樣。所以指向同一個實體,對c1的屬性修改,相當於c的屬性也改了。

三、棧和堆的特點

棧:

函式中定義的基本型別變數,物件的引用變數都在函式的棧記憶體中分配。
棧記憶體特點,數資料一執行完畢,變數會立即釋放,節約記憶體空間。
棧記憶體中的資料,沒有預設初始化值,需要手動設定。

堆:

堆記憶體用來存放new建立的物件和陣列。
堆記憶體中所有的實體都有記憶體地址值。
堆記憶體中的實體是用來封裝資料的,這些資料都有預設初始化值。
堆記憶體中的實體不再被指向時,JVM啟動垃圾回收機制,自動清除,這也是JAVA優於C++的表現之一(C++中需要程式設計師手動清除)。

注:

什麼是區域性變數:定義在函式中的變數、定義在函式中的引數上的變數、定義在for迴圈內部的變數