下载大文件时内存溢出情况分析解决

基于SpringBoot和阿里的OSS实现了一个下载文件的功能。

大概原理是这样的:

用户请求下载资源,服务端接收到请求之后从OSS中将用户需要的资源捞出来,然后以流的方式写给客户端。

遇到一个这样的问题:

下载小文件没有问题,在超过100M左右时会报错org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Java heap space

猜想

1、怀疑可能是资源没有关闭造成(不是)
2、堆配置太小(治标不治本)
3、代码问题(原因)

排查过程:

首先观察发送请求,请求下载一个大文件(2G);此时使用JavaVisualVM观察内存情况,会直观的看到有个byte数组的大小直线上升;
请求前:
在这里插入图片描述
可以看到byte[]仅占内存2%左右;
请求后:
在这里插入图片描述
可以看到byte[]数组内存占用达到了90%左右;

确定是这个数组的问题,检查代码,可以看到在代码中的做法是先将请求的文件从OSS中拿到,然后赋值给一个InputStream流

...
  // 从oss对象上获取文件内容
  InputStream is = ossObject.getObjectContent();
...

然后将is流中的内容再写到OutputStream实现类的输出流中

...
   os.write(buffer, 0, bytesRead);
...

最后将输出流中的内容通过OutputStream实现类的toByteArray()方法转换成字节数组;然后返回给客户端

...
   byte[] fileOut = os.toByteArray();
   return fileOut;
...

经过检查确定是byte数组的问题,当OSS中文件太大时byte数组的大小会持续顶内存,直到GC处理不过来,抛出 Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Java heap space异常。

解决

去掉中间变量,直接从Response中获取OutputStream流对象;从OSS中获取到文件之后直接通过从Response中获取OutputStream流对象写给客户端;这样我们的服务端只相当于提供了一个通道功能,我们服务端只负责通道的对接,而不用做文件的中转站,大大节省服务器资源;也解决了标题中的问题。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
java导入excel大量数据出现内存溢出的问题可以通过以下几种方法来解决: 1. 分批导入:将大量数据分成多个小批次导入,每次只处理一部分数据,避免一次性加载全部数据导致内存溢出。可以按照行或者列进行分批导入,读取一部分数据后进行处理,然后再读取下一部分数据。 2. 内存优化:在导入数据,可以优化内存使用,减少内存消耗。例如,使用SXSSF模式代替XSSF模式,SXSSF模式可以将Excel数据写入临文件而不是全部加载到内存中,减少内存压力。 3. 限制每次读取的数据量:可以通过设置读取数据的行数或者列数限制来减少内存使用。例如,使用Apache POI库的setReadWindow方法来限制每次读取的行数和列数。 4. 增加JVM内存:通过增加JVM的内存限制来避免内存溢出问题。可以通过调整-Xms和-Xmx参数来增加JVM的初始内存和最大内存限制。 5. 优化代码逻辑:检查和优化导入数据的代码逻辑,确保没有内存泄漏或者无用的数据加载。可以使用工具来进行代码分析,找出潜在的问题并进行优化。 6. 使用缓存机制:对于重复的数据,可以使用缓存机制来减少重复加载。可以将已经读取的数据缓存起来,在需要的候直接从缓存中获取,避免重复读取导致的内存占用过高。 7. 使用数据库存储:对于大量数据的导入,可以考虑将数据存储在数据库中,而不是全部加载到内存中。可以使用数据库的批量插入操作来提高导入效率。 综上所述,解决java导入excel大量数据出现内存溢出问题可以通过分批导入、内存优化、限制每次读取的数据量、增加JVM内存、优化代码逻辑、使用缓存机制以及使用数据库存储等方法来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

户伟伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值