java 9 compact strings memory mangement and garbage collection。

时间:2017-08-03 03:50:09

标签: string java-9

我知道java 9中的字符串表示有所改进。我也发现了一些相关的信息。我想更多地了解这一点,以及与以前的Java版本相比,如何减少内存使用量并改进垃圾收集。有几个问题只与这个主题有关,但并不完全相信那里的答案。提前谢谢。

2 个答案:

答案 0 :(得分:10)

在Java 8中

在Java 8 String中有一个字段char[] value - 一个字符占用两个字节,因为它代表一个完整的UTF-16代码单元。 Oracle对许多堆转储的分析得出两个结论:

  • 这些数组占据普通应用程序实时数据(包括标题和指针)的20%到30%之间。
  • 绝大多数字符串只需要ISO-8859-1(也称为Latin-1),这是一个字节。

重构String只使用一个字节用于Latin-1因此可以节省大约10%到15%的内存,并通过减少垃圾分配来提高运行时性能。

在Java 9中

在Java 9中,Stringbyte[] 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 254Aleksey 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