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

JVM堆内存调至8GB仍出现Java heap space OutOfMemoryError异常

问题根本原因

你当前代码的核心问题是将全量文件内容一次性加载到JVM堆内存,触发大内存占用:

  • 你使用ByteArrayOutputStream把整个文件的字节全部缓存到内存,1.5GB的文件仅存储本身就需要至少1.5GB的连续堆空间
  • ByteArrayOutputStream自动扩容时会调用Arrays.copyOf生成新的字节数组,扩容峰值需要占用2倍于文件大小的堆内存,这就是你调整到8GB堆仍可能报错的原因:要么JVM堆配置未实际生效,要么存在并发上传任务,要么堆内存存在碎片没有足够的连续空间分配大数组。

解决建议

方案1:分片上传(最推荐,长期方案)

将大文件拆分为固定大小的分片(单分片大小建议设置为8MB~32MB),逐片上传,服务端收到全部分片后合并文件:

  • 内存仅需占用单分片大小的空间,完全避免大内存占用问题,同时天然支持断点续传、失败重传
  • 改造逻辑:先计算文件总分片数并给分片编号,每次只读一个分片的字节上传,全部上传完成后调用服务端合并接口即可。

方案2:改造为流式上传

如果上传接口支持流输入,直接将文件流对接上传逻辑,去掉中间全量缓存的步骤:

  • 不需要通过ByteArrayOutputStream中转全量字节,直接用FileInputStream传递给上传逻辑,内存仅占用固定缓冲区的大小。

方案3:临时兼容方案(仅适用于2GB以内文件,应急使用)

如果暂时无法修改上传逻辑,可以做两处调整临时解决:

  1. 初始化ByteArrayOutputStream时直接指定文件大小为初始容量,避免扩容带来的双倍内存峰值:
// 替换原 ByteArrayOutputStream 初始化逻辑
ByteArrayOutputStream out = new ByteArrayOutputStream((int) channel.size());
  1. 确认JVM堆配置实际生效:在程序启动参数中添加-XX:+PrintFlagsFinal,运行时查看MaxHeapSize参数是否确实为8GB,避免配置未生效的问题。

注意:该方案存在int溢出风险,最多支持2GB以内的文件,不推荐作为长期方案使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 05:48:01