JEP 254:紧凑弦
概括
采用更节省空间的字符串内部表示形式。
目标
String
提高类和相关类的空间效率,同时保持大多数场景下的性能,并保留所有相关 Java 和本机接口的完全兼容性。
非目标
在字符串的内部表示中使用替代编码(例如 UTF-8)并不是我们的目标。随后的 JEP 可能会探索这种方法。
动机
该类的当前实现String
将字符存储在char
数组中,每个字符使用两个字节(十六位)。从许多不同应用程序收集的数据表明,字符串是堆使用的主要组成部分,而且大多数String
对象仅包含 Latin-1 字符。这些字符只需要一个字节的存储空间,因此char
这些对象的内部数组中有一半的空间String
未被使用。
描述
我们建议将类的内部表示String
从 UTF-16char
数组更改为byte
数组加编码标志字段。新String
类将根据字符串的内容存储编码为 ISO-8859-1/Latin-1(每个字符一个字节)或 UTF-16(每个字符两个字节)的字符。编码标志将指示使用哪种编码。
与字符串相关的类(例如AbstractStringBuilder
、StringBuilder
和 )StringBuffer
将更新为使用相同的表示形式,HotSpot VM 的固有字符串操作也是如此。
这纯粹是一个实现更改,没有对现有公共接口进行任何更改。没有计划添加任何新的公共 API 或其他接口。
迄今为止完成的原型设计工作证实了内存占用量的预期减少、GC 活动的大幅减少以及某些极端情况下的轻微性能下降。
有关更多详细信息,请参阅:
备择方案
我们尝试了 JDK 6 更新版本中的“压缩字符串”功能,该功能通过-XX
标志启用。启用后,String.value
将更改为引用Object
,并且将指向一个byte
数组(对于仅包含 7 位 US-ASCII 字符的字符串),或者指向一个char
数组。该实现不是开源的,因此很难维护并与主线 JDK 源代码保持同步。此后它已被删除。
测试
彻底的兼容性和回归测试对于对平台的这一基本部分进行更改至关重 要。
我们还需要确认我们已经实现了该项目的绩效目标。需要对内存节省进行分析。性能测试应该使用广泛的工作负载来完成,从集中的微基准测试到大规模服务器工作负载。
我们将鼓励整个 Java 社区对这一更改进行早期测试,以便识别任何剩余的问题。
风险和假设
优化内存字符存储很可能需要在运行时性能方面进行权衡。我们预计这将通过减少 GC 活动来抵消,并且我们将能够维持典型服务器基准测试的吞吐量。如果没有,我们将研究可以在内存节省和运行时性能之间取得可接受的平衡的优化。
最近的其他项目已经减少了字符串使用的堆空间,特别是JEP 192:G1 中的字符串重复数据删除。即使消除了重复项,如果更有效地编码,剩余的字符串数据也可以消耗更少的空间。我们假设该项目仍将提供与所需努力相称的收益。