本文转载自:
https://www.cnblogs.com/orange42/p/6168803.html 作者:Orange42 转载请注明该声明。
错误日志里偶尔会有getStream+has+already+been+called+for+this+response.html' target='_self'>OutputStream() has already been called for this response这个错误
最近发现了高概率复现条件,所以顺手解决了一下:
首先根据这个错误关键信息,得知是错误产生原因是response.getWriter()和response.getOutputStream()等接口在调用时发生了资源占用
然而事实上在这个项目中并没有使用response.getWriter()和response.getOutputStream(),那么就需要更深入的去查找错误的原因
首先高概率复现条件是在进行redis操作的时候,这两个接口是进行流输出的接口,根据关键字查找,从redis相关操作中发现了一行序列化操作有进行流相关的操作。
public static byte[] serialize(Object object) throws Exception { ObjectOutputStream oos = null; ByteArrayOutputStream baos = null; try { // 序列化 baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(object); byte[] bytes = baos.toByteArray(); return bytes; } catch (Exception e) { throw e; } }
八成就是这里没有close导致的bug了。再往深了看:
其中ByteArrayOutputStream用于捕获内存缓冲区的数据,转换成字节数组,但有趣的是对一个ByteArrayOutputStream进行close()操作没有任何效果,而且这样写不会产生重复关闭导致的Exception。
ObjectOutputStream用于进行序列化,这个没有close应该就是罪魁祸首了,但保险起见,还是两个操作都加上Close()
修改后代码如下:
public static byte[] serialize(Object object) throws Exception { ObjectOutputStream oos = null; ByteArrayOutputStream baos = null; try { // 序列化 baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(object); byte[] bytes = baos.toByteArray();
oss.close(); baos.close(); return bytes; } catch (Exception e) { throw e; } finally { if(oos != null){ oos.close(); } if(baos != null){ baos.close(); } } }
问题解决!