Java中零垃圾大字符串反序列化,庞大的对象问题
问题内容:
我正在寻找String
一种byte[]
在Java中反序列化a的方法,并尽可能减少产生的垃圾。因为我正在创建自己的序列化器和反序列化器,所以我拥有在服务器端(即序列化数据)和客户端(即反序列化数据)时实现任何解决方案的完全自由。
通过遍历char()并将每个(16位值)转换为2x 8位值,我设法有效地 序列化 了a
String
而不产生任何垃圾开销。有这方面一个很好的辩论在这里。一种替代方法是使用反射直接访问基础,但这不在问题的范围之内。String's``String.charAt(i)``char
String's``char[]
但是,对于我来说,如果byte[]
不创建char[]
两次 ,似乎不可能反序列化,这似乎很奇怪。
步骤:
- 创造
char[]
- 遍历
byte[]
并填写char[]
- 用
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
包并访问包私有的构造函数。这对于安全管理器来说不是一个好兆头,但是可以绕开它。