首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试将对象转换为字节数组时的频繁GC

尝试将对象转换为字节数组时的频繁GC
EN

Stack Overflow用户
提问于 2019-10-22 14:57:33
回答 1查看 129关注 0票数 0

我正在使用下面的代码将对象转换为字节数组。

代码语言:javascript
复制
ByteArrayOutputStream baoS= new ByteArrayOutputStream();        
objectOutputStream ooS = new ObjectOutputStream(baoS);
ooS.writeObject(object);        
ooS.flush();        
ooS.close();
return baoS.toByteArray();

我们面临着频繁的GC问题和生产环境的缓慢。我们在运行时有很多对象,上面的代码将被调用来将对象转换为字节数组。如果频繁调用,此代码会导致内存泄漏/ CPU使用量增加吗?传递的对象是一个列表。在用JVisualVM进行采样时,这种方法已成为瓶颈。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-22 17:12:15

如果可以的话,简单的解决方案就是添加更多的堆。根据请求量的不同,这可能比支付薪资来编写不同的解决方案更便宜。这种方式不会改变代码、发布验证等。

传递的对象是一个列表。在用JVisualVM进行采样时,这种方法已成为瓶颈。

如果列表是大容量的,那么现在堆上有两个大问题:

  1. 列表

的字节数组版本

2是欺骗性的。ByteArrayOutputStream中的默认缓冲区为32字节。大于此的消息将导致创建另一个两次较大的数组并复制数据。如果这还不够大,创建另一个数组并再次复制。等等,这是一项很大的工作!

现在,对同时传入的所有请求并行执行该操作。然后,当所有的工作都完成了,你需要收回所有那些巨大的东西。这就可以解释gc了。

下一个简单的解决方案是预先调整缓冲区的大小。如果您知道98%的消息小于16k大小,那么您可以直接声明:new ByteArrayOutputStream(16384);。现在,98%的数组副本从32个字节增长到16834字节。的确,对于那些实际上很小的消息来说,这是效率低下的,但也许这是一次净赢。

或者不是固定的缓冲区大小,也许您可以猜测:new ByteArrayOutputStream(guessBufferSize(theList));

更难的解决方案是,您可以尝试通过从堆中删除一些东西来减轻堆内存压力:将字节写到其他地方,比如磁盘上的临时文件,并将文件路径发送到jms发送小部件。写入磁盘会使事情变慢,但这样做可以减少堆的震荡,从而使事情变得更快。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58507070

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档