JDK9对String字符串的新一轮优化必不可少。转载本文请联系程序新视界公众号。String类可以说是Java编程中使用最多的类。如果能优化String字符串的性能,那程序的性能肯定会有很大的提升。这不是JDK9,对String字符串进行了改进和升级。在某些场景下,String字符串的内存可以减少一半,从而减少JVM的GC次数。String的底层存储在面试中,我们通常会说String字符串具有不可变的特性,每次都要创建新的字符串。那么,为什么String字符串是不可变的呢?先看String字符串的底层存储结构:value=original.value;this.hash=original.hash;}//...}你看到了什么?当我们new一个String对象的时候,对应的string其实是以char数组的形式存放在String对象内部的。而且这个char数组是final的,也就是说不可变的。这就是为什么我们说String字符串具有不可变的特性。当字符串发生变化,char数组不可变时,只能新建一个对象,一个新的char数组。底层存储的优化上面提到的情况是针对JDK8及之前的版本。在JDK9中,String中字符串的存储不再使用char数组,而是byte数组。publicfinalclassStringimplementsjava.io.Serializable,Comparable,CharSequence{@Stableprivatefinalbyte[]value;privatefinalbytecoder;@NativestaticfinalbyteLATIN1=0;@NativestaticfinalbyteUTF16=1;staticfinalbooleanCOMPACT_STRINGS;publicString(){this.value="".value;this.coder="".coder;}@HotSpotIntrinsicCandidatepublicString(Stringoriginal){this.value=original.value;this.coder=original.coder;this.hash=original.hash;}//...}不仅将char数组改为byte数组,增加了一个coder的成员变量。程序中,大部分字符串只包含英文字母和数字等字符,采用Latin-1编码,一个字符占一个字节。如果使用char,一个char占用两个字节,内存空间翻倍。但是,如果字符串中使用了超出Latin-1范围的字符,例如中文,则无法使用Latin-1来表达。这时JDK会使用UTF-16编码,所以占用的空间和老版本一样(使用char[])。编码器变量表示编码格式。目前,String支持两种编码格式,Latin-1和UTF-16。Latin-1需要存储在一个字节中,而UTF-16需要存储在2个字节或4个字节中。据说这个改进方案是JDK开发者利用大数据和人工智能调查了上千个应用程序的heapdump信息,得出的结论是大部分String都是用Latin-1字符编码表示的,只存储一个字节就够了,两个字节就完全浪费了。COMPACT_STRINGS属性用于控制是否开启String的压缩功能。默认情况下它是打开的。可以使用-XX:-CompactStrings参数关闭此功能。改进的好处改进的好处非常明显。首先,如果大部分项目都使用Latin-1字符集,内存占用会大大降低,同样的硬件配置可以支持更多的业务。当内存减少时,会进一步减少GC的次数,从而降低Stop-The-World的频率,这样也会提高系统的性能。总结随着JDK的迭代String,内存结构和方法也在不断演化。这是因为String字符串往往是JVM中占用内存最多的类。通过其转型升级,业绩提升将更加明显。