Skip to content

JEP 254: Compact Strings | 紧凑字符串

摘要

本 JEP 提议采用一种更省空间的内部字符串表示方法。

目标

在保持大多数场景下的性能和完全兼容所有相关 Java 和本地接口的同时,提高 String 类及其相关类的空间效率。

非目标

本 JEP 不旨在在字符串的内部表示中使用可替换的编码,如 UTF-8。后续的 JEP 可能会探索这种方法。

动机

String 类的当前实现将字符存储在一个 char 数组中,每个字符使用两个字节(16 位)进行存储。从许多不同应用程序收集到的数据表明,字符串是堆使用的主要组成部分,而且大多数 String 对象仅包含 Latin-1 字符。这些字符只需要一个字节的存储空间,因此这种 String 对象中内部 char 数组的一半空间未被使用。

描述

我们建议将 String 类的内部表示从 UTF-16 char 数组改为一个 byte 数组和一个编码标记字段。新的 String 类将根据字符串的内容存储字符的编码方式为 ISO-8859-1 / Latin-1(每个字符一个字节)或 UTF-16(每个字符两个字节)。编码标记将指示所使用的编码方式。

String 有关的类,如 AbstractStringBuilderStringBuilderStringBuffer,将被更新以使用相同的表示方法,HotSpot VM 的内部字符串操作也将进行更新。

这是纯粹的实现更改,没有对现有公共接口进行任何更改。没有计划添加任何新的公共 API 或其他接口。

迄今为止所做的原型工作证实了所预期的内存占用降低、GC 活动大量减少和一些边角情况下的小型性能回归。

有关详细信息,请参阅:

备选方案

我们尝试在 JDK 6 更新发布中使用“压缩字符串”功能,通过启用 -XX 标志实现。启用后,String.value 将更改为指向 byte 数组(仅包含 7 位 US-ASCII 字符的字符串)或指向 char 数组的 Object 引用。由于该实现未开源,因此难以维护和与主线 JDK 源代码保持同步。它已被删除。

测试

对于修改平台的如此基本的部分,需要彻底进行兼容性和回归测试。

我们还需要确认我们已实现了该项目的性能目标。需要进行内存节省分析。应使用各种工作负载进行性能测试,从专注的微基准测试到大型服务器工作负载。

我们将鼓励整个 Java 社区在该更改发生早期进行测试,以确定是否还存在任何问题。

风险和假设

优化字符存储的内存可能会带来运行时性能的权衡。我们预计这将由减少 GC 活动来抵消,并且我们将能够维持典型服务器基准测试的吞吐量。如果不是这样,我们将调查可以在内存节省和运行时性能之间取得可接受平衡的优化。

其他最近的项目已经减少了字符串使用的堆空间,特别是 JEP 192: G1 中的字符串去重。即使消除了重复项,如果更有效地编码,则剩余的字符串数据也可以减少空间。我们假定这个项目仍将提供与所需的一样的好处。