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

Java 字串常量池深度解析:記憶體模型、intern() 機制與效能優化

     編輯:Java 相關知識

字串常量池核心機制

Java 字串物件建立有兩種方式:字面值(String s = "abc")與 new String()。JVM 為減少重複物件創建,維護一塊特殊記憶體區域——字串常量池(String Constant Pool),儲存字串物件的引用而非物件本身(物件實體在堆中)。

運作流程詳解

字面值建立流程

  1. 編譯期確定字面值內容
  2. 執行時檢查常量池是否已有相同內容的字串引用
  3. 若存在 → 直接返回該引用;若不存在 → 在堆建立新字串物件,將引用存入常量池並返回
String s1 = "droid";  // 建立物件,引用入池
String s2 = "droid";  // 直接返回池中引用
System.out.println(s1 == s2); // true

new 建立流程

無論常量池是否有相同內容,new String("droid") 都會在堆中建立新物件,不進入常量池:

String s3 = new String("droid");
System.out.println(s1 == s3); // false

intern() 方法:手動入池

呼叫 intern() 可將堆中字串物件引用加入常量池:

String s4 = s3.intern(); // 檢查池中有無 "droid",有則返回池中引用,無則將 s3 引用入池並返回
System.out.println(s4 == s1); // true

常見誤區釐清

常量池儲存的是物件還是引用?

儲存的是引用。驗證:嘗試將 82MB 影片檔讀為字串並 intern(),設 -XX:PermSize=6m(Java 8 前常量池在永久代)不會 OOM,證明 char[] 實體不在常量池。

字串不可變性是前提

唯有 String 為 final 不可變,多執行緒共享同一物件才安全。若可變,一處修改會影響所有引用者。

效能權衡與 GC 行為

  • 優點:減少重複物件,節省記憶體
  • 成本:查找常量池(底層 HashTable)消耗 CPU,但開銷極低
  • GC 影響:早期版本常量池強引用導致物件無法回收,現代 JVM 引入弱引用機制已解決此問題

編譯期優化:常量折疊

String test = "a" + "b" + "c";

編譯期直接合併為 "abc",僅建立一個物件、一個池引用。javap -c 反編譯可見 ldc #2 // String abc。

實務建議

  1. 優先使用字面值,避免不必要的 new String()
  2. 大量重複業務字串(如「美國加利福尼亞州」)可呼叫 intern() 手動入池
  3. 避免在循環中大量 intern(),防止常量池膨脹影響效能
  4. Java 8+ 常量池移至堆中,PermGen 大小限制不再適用,但記憶體壓力仍需關注
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved