首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java 反射修改 String 底層字段:JDK 版本差異與不可變性本質

     編輯:程式設計疑難解答

嘗試與錯誤

程式碼試圖透過反射修改 String 的 value (char[]) 與 count (int) 字段,執行期拋出 NoSuchFieldException: count。

JDK 版本演進

JDK 版本String 內部結構備註
JDK 6/7char[] value; int offset; int count;支援 substring 共享陣列
JDK 8~12char[] value; (無 offset/count)substring 複製陣列,簡化結構
JDK 9+ (Compact Strings)byte[] value; byte coder;Latin-1 用 1 byte,UTF-16 用 2 byte

結論:count 字段在 JDK 7 後已移除,JDK 9 更換為 byte[] + coder。反射代碼強綁定舊版結構,故失敗。

String 不可變性設計意圖

  • 安全性:字串常用於類載入、檔案路徑、網路參數,不可變防止被竄改。
  • 線程安全:無狀態可自由共享。
  • 字串常量池:相同內容共享實例,節省記憶體。
  • HashCode 快取:不可變保證 hash 不變,適合作 Map Key。

反射破壞不可變的後果

String s = "hello";
Field f = String.class.getDeclaredField("value");
f.setAccessible(true);
char[] arr = (char[]) f.get(s);
arr[0] = 'H';  // 修改常量池中的 "hello" 變 "Hello"!
System.out.println("hello"); // 可能輸出 "Hello" (嚴重破壞 JVM 假設)

此行為屬於 Undefined Behavior,JVM 不保證結果,可能導致類載入錯誤、安全檢查繞過、JIT 優化失效。

正確做法

  • 需要可變字串 → 使用 StringBuilder / StringBuffer。
  • 需要修改現有字串 → 建立新字串 s = "H" + s.substring(1);。
  • 教學/研究 JVM 內部 → 閱讀 OpenJDK 原始碼,勿在生產碼使用反射修改 String。

總結

count 字段不存在於現代 JDK。String 設計為不可變,反射強改屬危險行為,請勿模仿。

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