当前位置: 首页 > 知识库问答 >
问题:

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

柴兴贤
2023-03-14

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

我已经设法通过遍历String的字符(String.charAt(i))并将每个char(16位值)转换为2x 8位值,从而有效地序列化了String,而不会产生任何垃圾开销。这里有一个很好的争论。另一种选择是使用反射直接访问String的底层char[],但这超出了问题的范围。

然而,如果不创建两次char[],我似乎不可能反序列化byte[],这看起来很奇怪。

程序如下:

  1. 创建char[]

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

当然,对这一点最明智的回应是“来吧,停止这样做,相信GC,原来的char[]将非常短暂,G1将立即摆脱它”,如果char[]小于G1区域大小的1/2,这实际上是有道理的。如果较大,char[]将被直接分配为一个巨大的对象(即自动传播到G1区域之外)。在G1中,这样的对象很难被有效地垃圾收集。这就是为什么每次分配都很重要。

对如何解决这个问题有什么想法吗?

非常感谢。

共有3个答案

姬歌者
2023-03-14

找到了一个使用简单的“秘密”本机Java库的有效解决方案

String longString = StringUtils.repeat("bla", 1000000);
char[] longArray = longString.toCharArray();
String fastCopiedString = SharedSecrets.getJavaLangAccess().newStringUnsafe(longArray);
皇甫飞光
2023-03-14

我找到了一个解决方案,如果你有一个非托管的环境,它是无用的。

java。lang.String类有一个包私有构造函数String(char[]值,布尔共享)

来源:

/*
* 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()长。toString()字符串。concat(字符串)字符串。替换(char,char)字符串。valueOf(char)

解决方案(或hack,无论你想怎么称呼它)是将类移动到java.lang包并访问包私有构造函数。这对安全管理器来说不是好兆头,但这可以规避。

薛修能
2023-03-14

在G1中,这样的对象很难被有效地垃圾收集。

这可能不再是真的,但您必须为自己的应用程序评估它。JDK Bugs 8027959和8048179引入了收集巨大、短暂对象的新机制。根据错误标志,您可能必须使用jdk版本≥8u40和≥8u60才能获得各自的好处。

感兴趣的实验选项:

-XX:+G1ReclaimDeadHumongousObjectsAtYoungGC

追踪:

-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC

有关这些功能的进一步建议和问题,我建议点击热点gc使用邮件列表。

 类似资料:
  • 问题内容: 我正在寻找一种在Java中反序列化a的方法,并尽可能减少产生的垃圾。因为我正在创建自己的序列化器和反序列化器,所以我拥有在服务器端(即序列化数据)和客户端(即反序列化数据)时实现任何解决方案的完全自由。 通过遍历char()并将每个(16位值)转换为2x 8位值,我设法有效地 序列化 了a 而不产生任何垃圾开销。有这方面一个很好的辩论在这里。一种替代方法是使用反射直接访问基础,但这不在

  • [GC(分配失败)[defnew:10931K->472K(12288K),0.0053905秒]10931K->10712K(39616K),0.0054285秒][times:user=0.00 sys=0.00,real=0.01秒] [GC(分配失败)[defnew:10712k->472k(12288k),0.0057686秒]20952k->20952k(39616k),0.00580

  • 问题内容: 我有以下字符串 我想反序列化一个类的对象 我正在使用python 2.6和2.7 问题答案:

  • 我尝试从一个用于存储Spring会话的Redis服务器反序列化String到Java对象,并且我想在Spring框架之外反序列化它。我认为Spring Redis序列化器可能使用默认字符集UTF-8来将Java对象序列化为字符串。 Redis中的字符串: 错误消息: 我知道用UTF-8在Byte[]和String之间的转换很可能是问题所在,但我还是想问一下,是否有人知道如何在不修改序列化部分的情况

  • 问题内容: 我正在阅读有关垃圾收集的信息,当我搜索字符串文字垃圾收集时,搜索结果令人困惑。 我需要澄清以下几点: 如果在编译时将字符串定义为文字字符串,那么是否会对其进行垃圾回收? 如果使用实习方法,那么它会被垃圾回收吗?在第1点中,它也将与文字区别对待。 有人提到只有在卸载类时才会对文字进行垃圾回收吗?是否有道理,因为我认为永远不会卸课。 问题答案: 如果在编译时将字符串定义为文字字符串,那么是

  • 本文向大家介绍java对象的序列化和反序列化,包括了java对象的序列化和反序列化的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了java对象的序列化和反序列化,供大家参考,具体内容如下 1. 什么是序列化        将对象转换为字节流保存起来,比如保存到文件里,并在以后还原这个对象,这种机制叫做对象序列化。(补充一句:把对象保存到永久存储设备上称为持久化) 2. 怎么实现序列化