Java 堆疊和堆
什麼是堆疊記憶體?
Java 中的堆疊是記憶體的一部分,包含方法、區域性變數和引用變數。堆疊儲存器始終以**後進先出(LIFO)**順序引用。區域性變數是在堆疊中建立的。
什麼是堆記憶體?
堆是包含物件的記憶體部分,也可能包含引用變數。例項變數在堆中建立的。
Java 中的記憶體分配
JVM 將記憶體劃分為以下部分。
- 堆
- 堆疊
- 程式碼
- 靜態
這種記憶體劃分是其有效管理所必需的。
- 程式碼部分包含位元組碼。
- 記憶體的堆疊部分包含方法、區域性變數和引用變數。
- 堆部分包含物件(也可能包含引用變數)。
- 靜態部分包含靜態資料/方法。
本地和例項變數之間的差異
例項變數在類中宣告而不是在方法內宣告的。
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
建立一個新幀。
變數 b
和 c
也將在堆疊中的幀 m2
中建立。
public void m2(int b){
boolean c;
}
同樣的,方法 m2
來呼叫方法 m3
。再次在堆疊頂部建立一個幀 m3
。
現在假設我們的方法 m3
正在為類 Account
建立一個物件,它有兩個例項變數 int p
和 int 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)
概要:
- 呼叫方法時,會在堆疊頂部建立一個幀。
- 一旦方法完成執行,控制流將返回到呼叫方法,並重新整理其相應的堆疊幀。
- 在堆疊中建立區域性變數。
- 例項變數在堆中建立並且是它們所屬物件的一部分。
- 在堆疊中建立引用變數。