Java中零垃圾大字符串反序列化,庞大的对象问题


问题内容

我正在寻找String一种byte[]在Java中反序列化a的方法,并尽可能减少产生的垃圾。因为我正在创建自己的序列化器和反序列化器,所以我拥有在服务器端(即序列化数据)和客户端(即反序列化数据)时实现任何解决方案的完全自由。

通过遍历char()并将每个(16位值)转换为2x 8位值,我设法有效地 序列化 了a
String而不产生任何垃圾开销。有这方面一个很好的辩论在这里。一种替代方法是使用反射直接访问基础,但这不在问题的范围之内。String's``String.charAt(i)``charString's``char[]

但是,对于我来说,如果byte[]不创建char[] 两次 ,似乎不可能反序列化,这似乎很奇怪。

步骤:

  1. 创造 char[]
  2. 遍历byte[]并填写char[]
  3. String(char[])构造函数创建字符串

由于Java的String不变性规则,构造函数复制char
[],从而产生2倍的GC开销。我总是可以使用机制来规避这一问题(不安全String分配+反射来设置char[]实例),但是我只想问一下是否有其他后果,除了打破关于String's不变性的所有约定。

当然,对此的最明智的回应是“继续,停止这样做并信任GC,原始文档char[]将非常短暂,而G1会立即删除它”,
如果char[]较小,这实际上是有道理的 超过G1区域大小的1/2 。如果更大,则char
[]将直接分配为巨大对象(即自动传播到G1区域之外)。很难有效地将这些对象收集到G1中。这就是每个分配都很重要的原因。

有关如何解决此问题的任何想法?

非常感谢。


问题答案:

我发现一个解决方案,如果您具有不受管理的环境,那将是无用的。

java.lang.String类有一个包私有构造String(char[] value, boolean share)

资源:

/*
* Package private constructor which shares value array for speed.
* this constructor is always expected to be called with share==true.
* a separate constructor is needed because we already have a public
* String(char[]) constructor that makes a copy of the given char[].
*/
String(char[] value, boolean share) {
    // assert share : "unshared not supported";
    this.value = value;
}

这是正在在Java中广泛使用,例如Integer.toString()Long.toString()String.concat(String)String.replace(char,char)String.valueOf(char)

解决方案(或破解,无论您想调用什么)是将类移至java.lang包并访问包私有的构造函数。这对于安全管理器来说不是一个好兆头,但是可以绕开它。