我知道java 9中的字符串表示有所改进。我也发现了一些相关的信息。我想更多地了解这一点,以及与以前的Java版本相比,如何减少内存使用量并改进垃圾收集。有几个问题只与这个主题有关,但并不完全相信那里的答案。提前谢谢。
答案 0 :(得分:10)
在Java 8 String
中有一个字段char[] value
- 一个字符占用两个字节,因为它代表一个完整的UTF-16代码单元。 Oracle对许多堆转储的分析得出两个结论:
重构String
只使用一个字节用于Latin-1因此可以节省大约10%到15%的内存,并通过减少垃圾分配来提高运行时性能。
在Java 9中,String
由byte[] value
支持,因此UTF-8字符只能使用一个字节。但是如果字符串同时使用UTF-8 和 UTF-16(甚至是UTF-32)字符会发生什么?
对于像UTF-8这样的可变大小的记录,这听起来像是一种情况,其中每个字符对一个字节和两个字节进行区分。但是,没有办法预测单个字符它将占用哪个阵列时隙,因此需要随机访问(例如charAt(int)
)来执行线性扫描。将随机访问性能从常数时间降低到线性时间是不可接受的回归。
相反,每个字符都可以用单个字节编码,在这种情况下,这是所选择的表示,或者如果其中至少有一个需要两个,则将使用两个字节对于他们所有人。新字段coder
表示字节如何编码字符,String
中的许多方法对其进行评估以选择正确的代码路径。
以下是String
构造函数的简化版本的外观:
// `char[] value` is the argument
if (COMPACT_STRINGS) {
byte[] val = StringUTF16.compress(value);
if (val != null) {
this.value = val;
this.coder = LATIN1;
return;
}
}
this.coder = UTF16;
this.value = StringUTF16.toBytes(value);
这里有几点需要注意:
COMPACT_STRINGS
,它是命令行标志XX:-CompactStrings
的实现,可以使用它来禁用压缩。StringUTF16
首先用于尝试将值数组压缩为单个字节,如果失败并返回null
,则将其转换为双字节。如果您想了解有关紧凑字符串(以及不明确的字符串连接)的更多信息,请查看JEP 254或Aleksey Shipilev’s talk(它还包括一些基准测试)。
答案 1 :(得分:2)
Java 9引入了String优化。 Java 9带有JEP 254(Compact Strings)功能。
“而不是char []数组,String现在表示为byte []数组。根据它包含的字符,它将使用UTF-16或Latin-1,即 - 每个字符串一个或两个字节String类中有一个新字段 - 编码器,它指示使用哪个变体。与压缩字符串不同,默认情况下启用此功能。如果需要(在主要使用UTF-16字符串的情况下),仍然可以通过-XX禁用:-CompactStrings。
此更改不会影响String或任何其他相关类的任何公共接口。许多类都经过重新设计以支持新的String表示形式,例如StringBuffer或StringBuilder。“
http://openjdk.java.net/jeps/254
<强>描述强>
我们建议将String类的内部表示从UTF-16字符数组更改为字节数组加编码标志字段。新的String类将存储根据字符串内容编码为ISO-8859-1 / Latin-1(每个字符一个字节)或UTF-16(每个字符两个字节)的字符。编码标志将指示使用的编码。
与String相关的类(如AbstractStringBuilder,StringBuilder和StringBuffer)将更新为使用相同的表示形式,HotSpot VM的内部字符串操作也将如此。
这纯粹是一个实现更改,不会更改现有的公共接口。没有计划添加任何新的公共API或其他接口。
迄今为止所做的原型制作工作证实了预期的内存占用减少,GC活动大幅减少以及某些极端情况下的性能回归较小。
有关详细信息,请参阅
http://cr.openjdk.java.net/~shade/density/state-of-string-density-v1.txt
http://cr.openjdk.java.net/~huntch/string-density/reports/String-Density-SPARC-jbb2005-Report.pdf
https://www.youtube.com/watch?v=wIyeOaitmWM
https://www.infoq.com/news/2016/02/compact-strings-Java-JDK9