You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ByteArrayOutputStream重赋值引发内存异常问题排查

内存错误问题分析与修复

你的代码出现内存溢出,核心问题不是旧的ByteArrayOutputStream没被GC回收,而是内存堆积的速度超过了GC回收的速度,或者getNewData()生成的单份数据本身就过大,直接占满了堆内存。另外代码里还有个低效的点:每次循环都重复打开/关闭文件输出流,虽然不会直接导致内存问题,但完全没必要。

具体优化方案:

  1. 复用文件输出流
    把FileOutputStream的创建移到循环外面,避免频繁打开关闭文件句柄,同时减少资源开销:

    try (OutputStream outputStream = new FileOutputStream("data.txt", true)) {
        ByteArrayOutputStream data = getNewData();
        while (data.size() > 0) {
            data.writeTo(outputStream);
            // 主动重置ByteArrayOutputStream,帮助GC更快回收内存
            data.reset();
            data = getNewData();
        }
    } catch (IOException ex) {
        throw new RuntimeException(ex);
    }
    
  2. 彻底避免内存堆积(最优解)
    如果能修改getNewData()的逻辑,直接把数据写入文件输出流,而不是先把所有数据缓存到ByteArrayOutputStream里,从根源上解决内存占用问题:

    try (OutputStream outputStream = new FileOutputStream("data.txt", true)) {
        // writeNewDataToStream直接将数据写入输出流,返回false表示无更多数据
        while (writeNewDataToStream(outputStream)) {
            // 循环直到数据写完
        }
    } catch (IOException ex) {
        throw new RuntimeException(ex);
    }
    
    // 替换原getNewData()方法
    private boolean writeNewDataToStream(OutputStream output) throws IOException {
        // 这里实现数据生成/读取逻辑,直接写入output
        // 示例:如果是读取某个数据源,边读边写
        // int bytesRead;
        // byte[] buffer = new byte[8192];
        // while ((bytesRead = input.read(buffer)) != -1) {
        //     output.write(buffer, 0, bytesRead);
        // }
        // return 是否还有下一批数据
    }
    

为什么原代码会内存溢出?

  • 如果getNewData()每次生成的ByteArrayOutputStream数据量极大(比如几百MB以上),单份数据就可能占满堆内存,直接触发OOM。
  • 即使单份数据不大,循环过程中旧的ByteArrayOutputStream还没被GC回收,新的又被创建,短时间内堆内存被大量对象占满,GC来不及清理,也会导致溢出。

内容的提问来源于stack exchange,提问作者thmasker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:12:33