JDK9對String字符串的新一輪優化
String類可以說是Java編程中使用最多的類瞭,如果能對String字符串的性能進行優化,那麼程序的性能必然能大幅提升。
這不JDK9就對String字符串進行瞭改進升級,在某些場景下可以讓String字符串內存減少一半,進而減少JVM的GC次數。
String的底層存儲
在面試的時候我們通常會說String字符串有不可變的特性,每次都要創建新的字符串。那麼,為什麼String字符串是不可變的呢?
先來看一下String字符串的底層存儲結構:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[]; public String() { this.value = "".value; } public String(String original) { this.value = original.value; this.hash = original.hash; } // ... }
看到什麼瞭?當我們new一個String對象時,對應的字符串其實是以char數組的形式存儲在String對象內部。而這個char數組是final的,也就是說不可變的。
這也就是為什麼我們說String字符串擁有不可變的特性,當字符串改變瞭,char數組不可變,就隻能創建一個新的對象,新的char數組瞭。
底層存儲的優化
上面說的情況是JDK8及以前版本,到瞭JDK9,String中字符串的存儲不再用char數組瞭,改用byte數組。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { @Stable private final byte[] value; private final byte coder; @Native static final byte LATIN1 = 0; @Native static final byte UTF16 = 1; static final boolean COMPACT_STRINGS; public String() { this.value = "".value; this.coder = "".coder; } @HotSpotIntrinsicCandidate public String(String original) { this.value = original.value; this.coder = original.coder; this.hash = original.hash; } // ... }
不僅將char數組改為byte數組,而且新增瞭一個coder的成員變量。
在程序中,絕大多數字符串隻包含英文字母數字等字符,使用Latin-1編碼,一個字符占用一個byte。如果使用char,一個char要占用兩個byte,會占用雙倍的內存空間。
但是,如果字符串中使用瞭中文等超出Latin-1表示范圍的字符,使用Latin-1就沒辦法表示瞭。這時JDK會使用UTF-16編碼,那麼占用的空間和舊版(使用char[])是一樣的。
coder變量代表編碼的格式,目前String支持兩種編碼格式Latin-1和UTF-16。Latin-1需要用一個字節來存儲,而UTF-16需要使用2個字節或者4個字節來存儲。
據說這一改進方案是JDK的開發人員用大數據和人工能智能,調研瞭成千上萬的應用程序的heapdump信息後,得出:大部分的String都是以Latin-1字符編碼來表示的,隻需要一個字節存儲就夠瞭,兩個字節完全是浪費。
COMPACT_STRINGS屬性則是用來控制是否開啟String的compact功能。默認情況下是開啟的。可以使用-XX:-CompactStrings參數來對此功能進行關閉。
改進的好處
改進的好處是非常明顯的,首先如果項目中使用Latin-1字符集居多,內存的占用大幅度減少,同樣的硬件配置可以支撐更多的業務。
當內存減少之後,進一步導致減少GC次數,進而減少Stop-The-World的頻次,同樣會提升系統的性能。
小結
隨著JDK的迭代String字符串的內存結構及方法等也在不斷地進行演變。這是因為String字符串往往是JVM中占用內存最多的類,通過對它的改造升級,對性能的提升會更加明顯。
到此這篇關於JDK9對String字符串的新一輪優化的文章就介紹到這瞭,更多相關JDK9對String字符串優化內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 關於Java中byte[] 和 String互相轉換問題
- Java String保存字符串的機制
- 詳解Java中String,StringBuffer和StringBuilder的使用
- Java基礎之Unsafe內存操作不安全類詳解
- 使用Java將字符串在ISO-8859-1和UTF-8之間相互轉換