我正在使用下面的代码将对象转换为字节数组。
ByteArrayOutputStream baoS= new ByteArrayOutputStream();
objectOutputStream ooS = new ObjectOutputStream(baoS);
ooS.writeObject(object);
ooS.flush();
ooS.close();
return baoS.toByteArray();我们面临着频繁的GC问题和生产环境的缓慢。我们在运行时有很多对象,上面的代码将被调用来将对象转换为字节数组。如果频繁调用,此代码会导致内存泄漏/ CPU使用量增加吗?传递的对象是一个列表。在用JVisualVM进行采样时,这种方法已成为瓶颈。
发布于 2019-10-22 17:12:15
如果可以的话,简单的解决方案就是添加更多的堆。根据请求量的不同,这可能比支付薪资来编写不同的解决方案更便宜。这种方式不会改变代码、发布验证等。
传递的对象是一个列表。在用JVisualVM进行采样时,这种方法已成为瓶颈。
如果列表是大容量的,那么现在堆上有两个大问题:
的字节数组版本
2是欺骗性的。ByteArrayOutputStream中的默认缓冲区为32字节。大于此的消息将导致创建另一个两次较大的数组并复制数据。如果这还不够大,创建另一个数组并再次复制。等等,这是一项很大的工作!
现在,对同时传入的所有请求并行执行该操作。然后,当所有的工作都完成了,你需要收回所有那些巨大的东西。这就可以解释gc了。
下一个简单的解决方案是预先调整缓冲区的大小。如果您知道98%的消息小于16k大小,那么您可以直接声明:new ByteArrayOutputStream(16384);。现在,98%的数组副本从32个字节增长到16834字节。的确,对于那些实际上很小的消息来说,这是效率低下的,但也许这是一次净赢。
或者不是固定的缓冲区大小,也许您可以猜测:new ByteArrayOutputStream(guessBufferSize(theList));
更难的解决方案是,您可以尝试通过从堆中删除一些东西来减轻堆内存压力:将字节写到其他地方,比如磁盘上的临时文件,并将文件路径发送到jms发送小部件。写入磁盘会使事情变慢,但这样做可以减少堆的震荡,从而使事情变得更快。
https://stackoverflow.com/questions/58507070
复制相似问题