MultipartFile类型接收上传文件报出的UncheckedIOException以及删除tomcat临时文件失败源码探索

1、描述异常背景:

因为需要分析数据,待处理excel文件的数据行数太大,手动太累,花半小时写了一个定制的数据入库工具,改成了通用的,整个项目中的万级别数据都在工具上分析,写SQL进行分析,但是遇到很疑惑的问题,文件上传结束收流时,tomcat的DisFileItem类的delete方法会自动调用,但是如果当前系统用户的权限不足,或是文件流在删除该临时文件之前未关闭都会导致删除失败,虽然接收流的业务操作都结束了,但是很是会报出糟心的UncheckedIOException:Cannot delete tomcat默认的临时文件路径+_00000000.tmp异常(剧透一下:运行时未关闭输入流,JVM还在等待用户关闭,存在引用无法回收,所以手动跟着路径去删除你都删不掉,所以跟着源码找根源)。

2、查找异常原因(并不是所有的异常都是你显式的写出来的,特别是轮子使用不仔细的内部异常)

以上请及其注意异常出现的根源:StandardServletMultipartResolver.java:134;

我们进去查看其源码得到

也就是说我们的请求文件接收成功了吗,但是删除临时文件的操作出现问题了:

java 复制代码
if (request.getFile(part.getName()) != null) {
                        part.delete();
   }

进入删除的代码下来:

注意这一句源码注释:

删除部件的基础存储,包括删除任何关联的临时磁盘文件。尽管容器将自动删除此存储,但此方法可用于确保在较早的时间执行此操作,从而保留系统资源。

仅当对部件实例进行垃圾回收时,才需要容器删除关联的存储。Apache Tomcat 将在关联的请求完成处理后删除关联的存储。其他容器的行为可能不同。

抛出:

IOException -- 如果在尝试删除部件时发生 I/O

那么我们进入到它的默认实现类的最终源码:

到这里我们大致是知道问题出在这个临时文件的删除上了。

但是为什么删除失败呢?只有可能是这行代码的问题:

如果输出的文件就是有问题的null那一定是删除不掉的,让我们找找源码:

这里一定是没有问题的,继续往下走:

由此处的信息可以知道作为缓冲的临时文件区域的输出流未完成,还在保持开启状态,很大的可能是缓冲前的输入的流还没完全关闭(我们明确知道的是在代码里获取了输入的流但是没有对流进行关闭),亦或有可能原本文件上传就是null(当然不可能了兄弟)

3、结合2查找真正导致输出文件流在删除之前关闭的原因

我们注意到简单的接口代码是:

java 复制代码
    @PostMapping("/upTopGoods")
    @ResponseBody
    public void upTopGoods(@RequestParam("fileName") MultipartFile fileName){
        if (Objects.nonNull(fileName)){
            excelUtil.setTopGoods(fileName);
        }
    }

这个流会在操作完成或输入流的字节被处理完之后没能主动关闭的话,很有可能出自于接口MultipartFile的性质需要我们自己关闭(所以才会有一次OOM异常,但是请注意一定不仅仅是这个导致的,BUG选手程序员要保持疑问)。

所以我们查看MultipartFile的源码试图找出问题所在:

以上是MultipartFile的输入流方法注释。

以上处理完数据之后我们对输入的流进行了关闭,测试一下看看是否解决了问题:

通过结果来看是完全没有问题的了。

本次排查问题寻根原理过程结束,拜拜!

相关推荐
华仔啊39 分钟前
Stream 代码越写越难看?JDFrame 让 Java 逻辑回归优雅
java·后端
ray_liang1 小时前
用六边形架构与整洁架构对比是伪命题?
java·架构
Ray Liang2 小时前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
Java水解2 小时前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端
SimonKing6 小时前
OpenCode AI辅助编程,不一样的编程思路,不写一行代码
java·后端·程序员
FastBean7 小时前
Jackson View Extension Spring Boot Starter
java·后端
Seven978 小时前
剑指offer-79、最⻓不含重复字符的⼦字符串
java
皮皮林55117 小时前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java
冰_河17 小时前
QPS从300到3100:我靠一行代码让接口性能暴涨10倍,系统性能原地起飞!!
java·后端·性能优化