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

从Oracle表获取25MB CLOB报OOM,求SpringBoot解决方案

问题描述

尝试从Oracle SQL表中获取约25MB的CLOB数据时,遇到以下错误:

WARNING: Resolved [org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Java heap space]

当前使用的SpringBoot代码如下:

public byte[] getData(String task) {
    StringBuilder sb = new StringBuilder();
    sb.append("select OUTPUT_file from tablea where task = ?");
    
    byte[] fileBytes = jdbcTemplate.query(sb.toString(), new Object[]{task}, (rs) ->{
        if(rs.next()){
        
            byte[] resByteArry =new byte[0];
        Clob clob = rs.getClob("OUTPUT_file");
        resByteArry =getByteArrayByStream(clob.getAsciiStream());
        return resByteArry;
        }else {
            return new byte[0];
        }
        
    });
    
    return fileBytes;
}

private byte[] getByteArrayByStream(InputStream ins) {

ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
    byte[] buffer = new byte[1024];
    int length =0;
    while( (length = ins.read(buffer,0,buffer.length)) !=-1){
        
        out.write(buffer,0,length);
        
    }
    out.flush();
    out.close();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
return out.toByteArray();

}

请问是否有办法成功获取该文件?同时求基于SpringBoot的其他替代实现方案。


解决方案

临时修复:调整JVM堆内存

如果只是临时解决这个问题,可以在启动SpringBoot应用时增加堆内存参数,比如:

java -jar your-app.jar -Xmx512m

将-Xmx512m调整到足够容纳25MB数据的大小即可,这样能一次性把CLOB数据加载到内存中。但这种方法仅适用于小体量CLOB,处理更大数据时仍会触发OOM,且可能引发其他内存相关问题。

最优方案:流式处理,避免全量数据加载

你的代码核心问题是将整个CLOB转换成byte[]存入内存,导致堆内存溢出。最优方案是采用流式处理,直接边读边输出/处理数据,不把全量数据加载到内存中。

基于SpringBoot的流式实现示例

1. 直接向客户端流式返回数据

修改接口方法,通过StreamingResponseBody将CLOB数据直接流式输出给客户端,无需转换成byte[]:

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

@GetMapping("/data/{task}")
public ResponseEntity<StreamingResponseBody> getDataStream(@PathVariable String task) {
    StreamingResponseBody responseBody = outputStream -> {
        String sql = "select OUTPUT_file from tablea where task = ?";
        jdbcTemplate.query(sql, new Object[]{task}, rs -> {
            if (rs.next()) {
                try (InputStream inputStream = rs.getClob("OUTPUT_file").getAsciiStream()) {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                        outputStream.flush();
                    }
                } catch (IOException e) {
                    throw new RuntimeException("读取CLOB数据失败", e);
                }
            }
        });
    };

    return ResponseEntity.ok()
            .header("Content-Type", "application/octet-stream")
            .body(responseBody);
}

2. 流式写入本地文件

如果需要将CLOB数据写入本地文件,同样可以采用流式处理:

import java.io.FileOutputStream;
import java.io.InputStream;

public void writeClobToFile(String task, String filePath) {
    String sql = "select OUTPUT_file from tablea where task = ?";
    jdbcTemplate.query(sql, new Object[]{task}, rs -> {
        if (rs.next()) {
            try (InputStream inputStream = rs.getClob("OUTPUT_file").getAsciiStream();
                 FileOutputStream outputStream = new FileOutputStream(filePath)) {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            } catch (IOException e) {
                throw new RuntimeException("写入文件失败", e);
            }
        }
    });
}

额外优化建议

  • 调整缓冲区大小:将原来的1024字节缓冲区改为4096或8192字节,减少IO交互次数,提升处理效率。
  • 强制使用try-with-resources:自动关闭流资源,避免资源泄漏,上述示例已采用该语法。
  • 更新Oracle JDBC驱动:确保使用最新版本的Oracle JDBC驱动,旧版本处理大CLOB时可能存在内存泄漏问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:42:50