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

Java String 效能優化深度解析:從記憶體結構到最佳實踐

     編輯:Java 相關知識

String 在 JVM 中的儲存結構

在 HotSpot JVM 中,一般 Java 物件的記憶體佈局包含物件頭(8 位元組)、基本型別資料、參考(4 位元組)以及對齊填充。String 類別在 JDK 6 中擁有 char[] value、int offset、int count、int hash 四個欄位。一個空的 char[] 陣列本身也是物件,含物件頭 8 位元組加長度 4 位元組,共 12 位元組,經對齊後佔 16 位元組。因此一個空 String 物件大約佔用 40 位元組(物件頭 8 + 陣列 16 + 三個 int 12 + 陣列參考 4)。實際 String 佔用空間可依字元長度 n 估算:8 * (int)(((n * 2) + 43) / 8) 位元組。

實戰案例:substring 導致的記憶體洩漏

某專案需解析 300 MB CSV 檔案,統計約 2 萬個唯一單詞(平均長度 15 字元)。依公式估算僅需 1.5 MB,但實際卻佔用數百 MB。主因在於大量使用 String.split() 或 substring() 取得單詞。JDK 6 中 substring 會共用原始 char[],僅透過 offset、count 記錄範圍。若從巨大字串截取少量子字串,原始大字串無法被 GC 回收,造成嚴重記憶體浪費。

解決方案:強制複製字元陣列

呼叫 new String(smallString.toCharArray()) 可建立只包含所需字元的新字串,斷開對原始大字串的引用。雖此法在截取總長度接近原文本時空間複雜度較高(O(n³)),但於「從大文本截取少量字串」的場景極為有效。

其他 String 使用優化建議

字串拼接選擇

  • 靜態字串:直接用 +,編譯器會最佳化為單一常數。
  • 動態字串:使用 StringBuilder(單執行緒)或 StringBuffer(多執行緒)的 append,避免產生大量暫時 String 物件。

String 建構方式差異

  • String s = "Hello":優先從字串常數池取得實例,不存在才建立。
  • String s = new String("Hello"):每次都在堆上建立新物件,若常數池已有相同內容則再複製一份。

避免重複建立相同字串的策略

不建議使用 intern(),因它使用永久代(PermGen)且為全域池,易導致 OOM。較佳做法是自行維護 HashMap<String, String> 做快取:

private String getCacheWord(String key) {
    String tmp = cacheMap.get(key);
    if (tmp != null) return tmp;
    cacheMap.put(key, key);
    return key;
}

結語

理解 String 記憶體模型、substring 共用陣列機制、拼接與建構的最佳實踐,並配合自訂快取,能有效解決大文本處理中的記憶體壓力。這些原理亦可推廣至其他 String 相關效能調優場景。

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