Java 堆疊和堆

什麼是堆疊記憶體?

Java 中的堆疊是記憶體的一部分,包含方法、區域性變數和引用變數。堆疊儲存器始終以**後進先出(LIFO)**順序引用。區域性變數是在堆疊中建立的。

什麼是堆記憶體?

堆是包含物件的記憶體部分,也可能包含引用變數。例項變數在堆中建立的。

Java 中的記憶體分配

JVM 將記憶體劃分為以下部分。

  1. 堆疊
  2. 程式碼
  3. 靜態

這種記憶體劃分是其有效管理所必需的。

  • 程式碼部分包含位元組碼
  • 記憶體的堆疊部分包含方法、區域性變數和引用變數。
  • 部分包含物件(也可能包含引用變數)。
  • 靜態部分包含靜態資料/方法

本地和例項變數之間的差異

例項變數在類中宣告而不是在方法內宣告的。

class Student{ 
int num; //num is  instance variable 
public void showData{}

區域性變數在方法中宣告,包括方法引數。

public void sum(int a){
int x = int a +  3;
//a , x are local variables;
}

堆疊和堆之間的區別

讓我們舉個例子來更好地理解這一點。

想一下你的 main 方法呼叫方法 m1

public void m1{
int x=20
}

在 Java 堆疊中,將從方法 m1 建立一個幀。m1 中的變數 X 也將在堆疊 m1 的幀中建立。

方法 m1 呼叫方法 m2。在堆疊中,在 m1 幀的頂部為 m2 建立一個新幀。

變數 bc 也將在堆疊中的幀 m2 中建立。

public void m2(int b){
boolean c;
}

同樣的,方法 m2 來呼叫方法 m3。再次在堆疊頂部建立一個幀 m3

現在假設我們的方法 m3 正在為類 Account 建立一個物件,它有兩個例項變數 int pint q

Account {
             Int p;
             Int q;
}

這是方法 m3 的程式碼

public void m3(){
    Account ref = new Account();
    //more code
}

語句 new Account() 將在堆中建立一個 Account 物件。

引用變數 ref 將在堆疊中建立。賦值 = 運算子將使引用變數指向堆中的物件。

一旦方法完成執行。控制流程將返回撥用方法。在這裡指的是方法 m2

方法 m3 的堆疊將被清除。

由於引用變數將不再指向堆中的物件,因此它可以進行垃圾回收。

方法 m2 完成執行後。它將從堆疊彈出,其所有變數將被重新整理,不再可用。同樣這適用於方法 m1

最終,控制流程將返回程式的起始點。通常,這是 main 方法。

如果 Object 有一個引用作為其例項變數怎麼辦?比如下面,

public static void main(String args[]) {
    A parent = new A(); 
    //more code } 
    class A{ 
        B child = new B(); 
        int e; //more code 
    } 
    class B{ 
        int c; 
        int d;  
        //more code 
    }
}

在這種情況下,引用變數 child 將在堆中建立,而堆又將指向其物件,如下圖所示。

![Java Stack and Heap](/img/JavaJava Stack and Heap.jpg)

概要:

  • 呼叫方法時,會在堆疊頂部建立一個幀。
  • 一旦方法完成執行,控制流將返回到呼叫方法,並重新整理其相應的堆疊幀。
  • 在堆疊中建立區域性變數。
  • 例項變數在堆中建立並且是它們所屬物件的一部分。
  • 在堆疊中建立引用變數。