Java 記憶體模型深度解析:堆與棧的區別、對象分配與 GC 回收機制
Java 堆
- 存放所有對象實例(
new 出來的對象)及數組。
- 全局共享,所有線程可訪問。
- GC 主要工作區域:釋放無引用對象內存。
Java 棧
- 線程私有,生命周期與線程同步。
- 存放基本類型局部變量、對象引用、方法調用幀(局部變量表、操作數棧、動態鏈接、返回地址)。
- 後進先出,方法調用壓棧,返回彈棧。
- 空間遠小於堆,分配速度極快。
圖解內存分配流程
public class TestMemory {
public static void main(String[] args) {
int i = 666; // line1: 棧存基本類型
Object obj = new Object(); // line2: 棧存引用 obj → 堆存 Object 實例
TestMemory tm = new TestMemory(); // line3: 棧存引用 tm → 堆存 TestMemory 實例
tm.test(obj); // line4: 壓棧 test 幀,參數引用 obj
}
private void test(Object params) { // line6: test 幀
String str = params.toString(); // line7: 堆創建 String,棧存引用 str
System.out.println(str); // line8
} // line9: test 幀彈棧,str 引用失效
} // main 結束,main 幀彈棧,所有引用失效,堆對象等待 GC

關鍵差異總結
| 維度 | 堆 | 棧 |
| 存儲內容 | 對象實例、數組 | 基本類型、對象引用、方法幀 |
| 共享性 | 線程共享 | 線程私有 |
| 生命周期 | GC 管理,無引用時回收 | 隨方法調用/返回自動分配釋放 |
| 空間大小 | 大(GB 級) | 小(MB 級,默認 1MB/線程) |
| 分配速度 | 較慢(需 GC 配合) | 極快(指針移動) |
實戰啟示
- 大對象、長生命周期 → 堆;小臨時變量 → 棧(逃逸分析可標量替換)。
- 避免在循環中創建大量臨時對象,增加 GC 壓力。
- 棧溢出(
StackOverflowError)常見於遞歸過深;堆溢出(OutOfMemoryError)常見於內存洩漏或堆過小。