Java堆、棧、常量池、成員變量和局部變量

靜態成員變量放在堆還是棧?都不是,放在方法區。

Java內存主要分成以下幾塊:

  • 堆heap【new出來的空間和數組空間,存放對象、數組,數據不能共享】
  • 虛擬機棧(局部變量表、操作棧、動態連接、方法返回地址)
  • 本地方法棧(native method stack)【操作系統的本地方法所需要的空間,存放局部變量、引用】
  • 方法區(method area,也叫元數據區-Metaspace)【所有對象數據共享區域,存儲靜態變量和普通方法、靜態方法、常量、字符串常量(嚴格說存放在常量池,堆和棧都有)等類信息,說白了就是保存類的模板】
  • 程序寄存器(program counter register)【速度最快且空間最小的一塊區域,由編譯器分配,我們對此沒有直接的控制權】

注:方法區(元數據區)是一個獨立區域,既不屬於堆,也不屬於棧,在類加載的時候只運行一次。

JVM 內存佈局-具體如下圖所示:

Java堆、棧、常量池、成員變量和局部變量

Java 應用運行時使用的全部存儲類型

  • 寄存器:最快的存儲區,由編譯器根據需求進行分配,我們在程序中無法控制。
  • 棧:存放基本類型的變量數據和對象的引用,但對象本身不存放在棧中,而是存放在堆(new 出來的對象)或者常量池中(字符串常量對象存放在常量池中)。
  • 堆:存放所有new出來的對象或數組。
  • 靜態域:存放靜態成員(static定義的)。 ---- 方法區
  • 常量池:存放字符串常量和基本類型常量(public static final)。
  • 非RAM存儲:硬盤等永久存儲空間。

(1) 棧中的數據大小和生命週期是可以確定的,當沒有引用指向數據時,這個數據就會消失。堆中的對象 -- 由垃圾回收器負責回收,因此大小和生命週期不需要確定,具有很大的靈活性。

(2) 對於字符串:其對象的引用都是存儲在棧中的,如果是編譯期已經創建好(直接用雙引號定義的)的就存儲在常量池中,如果是運行期(new出來的)才能確定的就存儲在堆中。對於equals相等的字符串,在常量池中永遠只有一份,在堆中有多份。

成員變量和局部變量:

成員變量 - 就是方法外部,類的內部定義的變量;

局部變量 - 就是方法或語句塊內部定義的變量。局部變量必須初始化。

形式參數是局部變量,局部變量的數據存在於棧內存中。棧內存中的局部變量隨著方法的消失而消失。

成員變量存儲在堆中的對象裡面,由垃圾回收器負責回收。

在java中只要是成員變量,一旦它所在類被實例化後,都是放在堆內存的,不管它是不是基礎類型。局部變量才是放在棧內存的。


分享到:


相關文章: