时间:2021-05-20
String类可以说是Java编程中使用最多的类了,如果能对String字符串的性能进行优化,那么程序的性能必然能大幅提升。
这不JDK9就对String字符串进行了改进升级,在某些场景下可以让String字符串内存减少一半,进而减少JVM的GC次数。
在面试的时候我们通常会说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字符串优化内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
Java分割字符串java.lang.String的split()方法,JDK1.4orlaterpublicString[]split(Stringregex
在C++中则把字符串封装成了一种数据类型string,可以直接声明变量并进行赋值等字符串操作。以下是C字符串和C++中string的区别:C字符串string对
String字符串对象1.介绍 String对象,对字符串进行操作,如:截取一段子串、查找字符串/字符、转换大小写等等。2.定义方式2.1newString(
StrReverse函数返回字符串,此字符串与指定字符串顺序相反。StrReverse(string1)string1参数是要进行字符反向的字符串。如果stri
String字符串常量StringBuffer字符串变量(线程安全)StringBuilder字符串变量(非线程安全)简要的说,String类型和StringB