使用ByteArray进行对象序列化反序列化跨运行时类型异常求助
问题根因
你代码里有3个核心错误,直接导致了跨环境反序列化类型异常:
- 第一个也是最严重的错误:批量入库逻辑写死了所有记录的blob内容
看写入代码逻辑:你先把当前方法入参里的单个invocationData的参数、返回值序列化生成字节数组,再把invocationData加入缓存列表,等缓存满了批量入库的时候,循环所有缓存的记录,但是所有记录都复用了最开始生成的那一份字节数组,也就是说除了第一个触发批量写入的记录之外,其他所有记录存的blob都是错的。同一运行时你大概率是缓存大小设为1,每次批量入库只有1条记录,刚好碰对结果,跨环境运行缓存被填满多几条记录就全乱了,自然类型对不上。 - 第二个错误:序列化和反序列化的API不匹配
你写入返回值的时候用的是writeObject()方法,如果返回值是基本类型,writeObject()会自动装箱为对应的包装类(比如boolean转Boolean)再序列化,序列化结果里带的是对象的元信息。但是你反序列化的时候,碰到boolean类型就调用readBoolean()读基本类型,这个API是对应writeBoolean()的写入结果的,和writeObject()写入的装箱对象结构完全不匹配,读出来的值自然是错的。 - 第三个错误:读取输入参数字节数组的逻辑有截断风险
你读取参数blob的时候用available()判断长度,这个方法返回的是当前可无阻塞读取的字节数,不是整个blob的总长度,很容易导致字节数组长度不够,序列化数据被截断,反序列化自然出错。
修复方案
- 先修批量写入的bug:把参数、返回值的序列化逻辑移到循环内部,每条记录单独生成自己的blob字节数组,或者把序列化后的字节数组存到
InvocationData对象里,不要在循环外公用同一个字节数组变量。 - 统一反序列化API:所有返回值都用
readObject()读取,读完之后再根据返回类型做拆箱即可,示例代码:
// 反序列化返回值部分修改为 rvIn = new ObjectInputStream(rvBis); Object rawObj = rvIn.readObject(); switch (returnType) { case "boolean": returnValue = (Boolean) rawObj; break; case "int": returnValue = (Integer) rawObj; break; // 其他基本类型同理做拆箱转换 default: returnValue = rawObj; break; }
- 修复参数读取逻辑,直接用
rs.getBytes()读取完整的blob字节数组,不要用流读:
// 输入参数读取部分修改为 byte[] inputArgsByteArray = rs.getBytes(5); ByteArrayInputStream bis = new ByteArrayInputStream(inputArgsByteArray);
内容的提问来源于stack exchange,提问作者alectogeek
相关产品推荐
相关产品推荐

