为了账号安全,请及时绑定邮箱和手机立即绑定

ThreadLocal<ByteArrayOutputStream> 导致 OutOfMemory

ThreadLocal<ByteArrayOutputStream> 导致 OutOfMemory

千巷猫影 2021-09-12 19:41:23
当我的类结构像这样时,我最终会遇到 OutOfMemory 错误。DataHandler由8个线程的固定池调用(没有外部线程池管理。固定池创建一次,执行一次,如果一个线程死亡,则不创建新线程)。一次,多个线程调用 DataHandler,但由于 byteArrayOutputStreamBuffer 是 threadLocal,每个线程都有自己的本地缓冲区。每个线程获取数据,调用 HandleData(),一旦完成,重复循环。传递的数据大小为 2 GB。因此,预计占用的总内存最多为(2 GB + 字节数组流的大小)* 线程数。数组流的最大大小应为 4 GB(由于调整内存大小而导致数据翻倍)。所以预期的总堆为 6*8 = 48 GB。堆被配置为处理更多(我已经尝试过高达 300 GB),但这个问题仍然存在。public class DataHandler {    private static ThreadLocal<ByteArrayOutputStream> byteArrayOutputStreamBuffer =        new ByteArrayOutputStream();    void HandleData(byte[] data) {        ByteArrayOutputStream byteArrayOutputStream = byteArrayOutputStreamBuffer.get();        File tempFile = new File(getFileName());        try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) {            byteArrayOutputStream.write(data);            fileOutputStream.write(byteArrayOutputStream.toByteArray());        } finally {            byteArrayOutputStream.reset();        }    }}如果我删除中间的 ByteArrayOutputStream,则没有 OOM。我试图找到一个解释为什么 ByteArrayOutputStream 会导致 OOM。编辑:我看到 toByteArray() 也会增加 2 GB,所以总数为 64 GB。
查看完整描述

1 回答

?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

AByteArrayOutputStream最多可以容纳Integer.MAX_VALUE - 8字节(比 2Gb 少 8 个字节),因为它将数据存储在单个 中byte[],并且数组长度限制为该值。

如果您尝试放入更多数据,它会抛出一个OutOfMemomoryError.

由于您输入了这么多数据,因此可能会发生这种情况。

ByteArrayOutputStream在这种情况下你不能使用。

但你为什么需要它?为什么不将 存储FileOutputStream在 ThreadLocal 中?


查看完整回答
反对 回复 2021-09-12
  • 1 回答
  • 0 关注
  • 238 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信