首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 內存模型深度解析:堆、棧、方法區與變量存儲全景圖

     編輯:Java 相關知識

JVM 運行時數據區總覽

+-------------------------+
|      方法區              |  類信息、常量、靜態變量、JIT編譯代碼
|   (Metaspace/JDK8+)     |
+-------------------------+
|         堆               |  new 出來的對象、數組(所有線程共享)
|   (GC 主戰場)           |
+-------------------------+
|   虛擬機棧 (線程私有)    |  棧幀:局部變量表、操作數棧、動態鏈接、方法返回地址
|   本地方法棧             |  Native 方法調用
|   程序計數器             |  當前線程執行字節碼行號
+-------------------------+

棧:線程私有,生命週期與線程同步

  • 存儲:基本類型局部變量、對象引用、方法參數、返回值
  • 特點:分配快、自動釋放、大小固定
  • 棧幀結構:每次方法調用創建一幀,包含局部變量表(Slot)、操作數棧

堆:對象實例的大本營

  • 所有 new 對象、數組在這裡分配
  • GC 管理:新生代、老年代、大對象直接進老年代
  • 引用變量在棧,對象實體在堆,「引用指向對象」

方法區與常量池

運行時常量池

  • Class 文件常量池的運行時表示
  • 包含字面量、符號引用
  • String.intern() 可將字符串放入常量池

String 存儲機制深度剖析

創建方式存儲位置示例
字面量常量池String s = "abc";
new String()堆String s = new String("abc");
編譯期常量拼接常量池(優化)"a" + "b" + "c" → "abc"
運行期變量拼接堆 (StringBuilder)s1 + s2
String s1 = "abc";
String s2 = "abc";        // s1 == s2 → true (常量池同一引用)
String s3 = new String("abc");
String s4 = new String("abc"); // s3 == s4 → false (堆不同對象)
s3.intern() == s1         // true (手動入池)

變量分類與存儲位置對照表

| 變量類型 | 修飾符 | 存儲位置 | 生命週期 | |----------|--------|----------|----------| | 實例變量 | 無/非 static | 堆 (對象內部) | 與對象同在 | | 類變量 | static | 方法區 | 與類同在 | | 局部變量 | 無 | 棧 (棧幀局部變量表) | 方法執行期間 | | 方法參數 | 無 | 棧 (棧幀局部變量表) | 方法調用期間 |

實戰案例分析

public void test() {
    int date = 9;                    // 基本類型局部變量 → 棧
    Test test = new Test();          // test引用→棧,對象→堆
    test.change(date);               // 參數傳值,i在新棧幀
    BirthDate d1 = new BirthDate(7,7,1970); // d1引用→棧,對象→堆
} // 方法結束:棧幀彈出,date/test/d1引用消失;堆對象等待 GC

核心結論

  1. 基本類型 + 引用變量 → 棧(線程私有,隨棧幀生滅)
  2. new 對象/數組 → 堆(線程共享,GC 管理)
  3. 字面量/編譯期常量 → 常量池(方法區,全局唯一)
  4. 參數傳遞本質是值傳遞:基本類型傳值,引用類型傳引用的副本

理解內存模型是排查 OOM、優化性能、寫出高質量並發代碼的前提。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved