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

Flux<DataBuffer>引发ByteBuf内存泄漏,求解决方案

解决ByteBuf未释放的内存泄漏问题

问题根源

你当前的代码只释放了blockLast()获取到的最后一个DataBuffer,但Flux<DataBuffer>流中的其他缓冲区在正常写入、超时或异常场景下可能没有被释放。DataBufferUtils.write默认不会自动释放写入后的DataBuffer,仅手动处理最后一个元素远远不够,这就是导致ByteBuf.release() was not called before it's garbage-collected异常的原因。

修复方案

1. 启用自动释放+兜底丢弃处理

修改代码,利用DataBufferUtils.write的重载方法开启自动释放,并添加doOnDiscard确保异常/中断场景下的缓冲区也能被释放:

private File createFileFromDataBuffer(Flux<DataBuffer> dataBuffer, String fileName, int timeoutInMin) {
    File tempFile = null;
    try {
        Path tempDir = Files.createTempDirectory("xyz");
        tempFile = new File(tempDir.toFile(), fileName);

        try (OutputStream os = new FileOutputStream(tempFile)) {
            DataBufferUtils.write(dataBuffer, os, true)
                    // 兜底处理:任何被丢弃的DataBuffer都会被释放
                    .doOnDiscard(DataBuffer.class, DataBufferUtils::release)
                    .blockLast(Duration.ofMinutes(timeoutInMin));
        }
    } catch (IOException e) {
        log.error("Error in API", e);
    }
    return tempFile;
}

关键修改说明

  • autoRelease=true:DataBufferUtils.write的第三个参数设为true后,每个DataBuffer成功写入输出流后会自动调用DataBufferUtils.release()释放,覆盖正常流程下的释放需求。
  • doOnDiscard:处理超时、IO异常等中断场景中未被正常处理的DataBuffer,确保这些缓冲区不会被遗漏,彻底避免内存泄漏。
  • 移除了不必要的share()调用:blockLast是唯一订阅者,共享流没有意义,反而可能引入额外的订阅问题。
  • 删除了手动保存和释放dataBufferTemp的逻辑:自动释放已经处理了所有DataBuffer,手动释放反而可能导致重复释放的错误。

额外注意事项

  • 始终使用DataBufferUtils工具类来释放DataBuffer,不要直接调用ByteBuf的release()方法——不同的DataBuffer实现(比如Netty的NettyDataBuffer)有特定的释放逻辑,工具类会统一处理。
  • 如果流中存在异常终止的情况,确保所有分支都能触发缓冲区释放,doOnDiscard是可靠的兜底手段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:01:03