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

Java 內存模型深度解析:棧與堆的分工協作與 String 常量池機制

     編輯:Java 相關知識

核心結論先行

特性棧堆
存取速度極快 (僅次於寄存器)較慢 (動態分配)
靈活性大小/生命週期須編譯期確定動態分配,GC 自動回收
存儲內容基本類型變量、對象引用對象實例、數組、包裝類對象
共享特性基本類型字面值可共享對象引用指向同一實例可共享

基本類型與字面值:棧上的共享機制

int a = 3;
int b = 3;

編譯器處理:

  1. 建立引用 a,棧中創建字面值 3,a 指向它
  2. 建立引用 b,發現棧已有 3,直接指向同一地址
  3. 結果:a、b 共享同一字面值 3

關鍵區別:修改 a = 4 時,編譯器重新查找/創建 4,a 指向新地址,b 仍指向 3。基本類型賦值修改的是引用指向,不影響其他引用。這與對象引用共享時修改內部狀態會互相影響本質不同。

包裝類與 String:堆上的對象語義

  • Integer, Double, String 等為包裝類,使用 new 在堆創建實例
  • JDK 5+ 自動裝箱:Integer i = 3 → Integer.valueOf(3) (緩存 -128~127)

String 的特殊性:雙重創建路徑

方式一:new String("abc") — 堆上創建新對象

String s1 = new String("abc");
String s2 = new String("abc");
s1 == s2; // false,兩個獨立堆對象

方式二:String str = "abc" — 常量池機制

JVM 內部步驟:

  1. 定義引用 str
  2. 檢查字符串常量池 (JDK 7+ 在堆中) 是否有 "abc"
  3. 無則創建字面值並建立 String 對象入池;有則直接返回池中對象引用
  4. str 指向池中對象

驗證代碼

String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2); // true,同一池對象

str1 = "bcd";
System.out.println(str1 == str2); // false,str1 指向新對象 "bcd"
System.out.println(str1 + ", " + str2); // bcd, abc

實戰建議

  1. 優先使用字面量:String s = "text" 利用常量池節省內存、提升速度
  2. 頻繁拼接用 StringBuilder:String 不可變,拼接產生大量臨時對象
  3. 比較內容用 equals():== 比較引用地址,equals() 比較字符序列
  4. 理解 intern():手動將堆上 String 放入常量池,返回池中引用

JDK 版本演進補充

  • JDK 6:常量池在永久代 (PermGen),大小固定,易 OOM
  • JDK 7+:常量池移至堆,受 GC 管理,動態擴縮
  • JDK 8+:永久代移除,元空間 (Metaspace) 存儲類元數據
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved