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

Java String.intern() 內存模型深度解析:JDK 6/7/8 演變

     編輯:Java 相關知識

String.intern() 基本語義

String.intern():檢查字符串常量池中是否存在內容相同的字符串,若存在返回池中引用;否則將該字符串放入池並返回引用。目的是減少重複字符串對象,節省記憶體。

字符串常量池演變史

版本常量池位置默認桶數量關鍵變化
JDK 6PermGen(永久代)1009大小固定,易 OOM
JDK 7u40 前Heap(堆)1009移出 PermGen,受堆大小限制
JDK 7u40+Heap60013桶數大幅增加,減少哈希衝突
JDK 8+Heap60013PermGen 移除,改為 Metaspace

實測驗證:JDK 6 vs JDK 7

測試代碼

public class StringPoolTest {
    public void testStringPoolWithLongString() {
        long i = 0;
        while (true) {
            String longString = "This is a very long string... " + i;
            longString.intern();
            i++;
        }
    }
    public static void main(String[] args) {
        new StringPoolTest().testStringPoolWithLongString();
    }
}

JDK 6 (1.6.0_29) 現象

JDK 6 PermGen GC

  • PermGen 反覆 GC,曲線呈鋸齒狀
  • 說明:常量池在 PermGen,滿時觸發 Full GC 回收無用字符串
  • 風險:PermGen 只有幾十 MB,大量 intern() 易導致 OutOfMemoryError: PermGen space

JDK 7 (1.7.0_67) 現象

JDK 7 PermGen 平穩

JDK 7 Heap GC

  • PermGen 曲線平穩,無分配波動
  • Heap 不斷分配新對象,頻繁觸發 Young GC
  • 說明:常量池已移至 Heap,受 -Xmx 限制,空間彈性大得多

性能與最佳實踐建議

  • JDK 6:不推薦大量使用 intern(),性能顯著下降且極易 OOM。
  • JDK 7+:常量池在堆中,空間受物理記憶體限制,**可有效減少重複字符串佔用**,適合大量去重場景(如解析大量重複鍵值的 JSON、日志分析等)。
  • 調優參數:-XX:StringTableSize=60013(JDK 7u40+ 默認值),可根據預估不同字符串數量調大(需為質數),減少哈希衝突提升查找速度。
  • 替代方案:若僅需去重,考慮 ConcurrentHashMap 自行維護池,可控性更強。

總結

String.intern() 的行為隨 JVM 版本劇烈變化。JDK 6 時代是「危險區」,JDK 7+ 遷移至堆後成為「實用工具」。理解底層內存模型演變,才能在正確場景下正確使用,避免生產事故。

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