1. 程式人生 > >Java中的棧和堆

Java中的棧和堆

首地址 行數 str 垃圾回收機制 圖片 eap show 數據類型 空值

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循環內部的變量

Java中的棧和堆