序列化就是一种处理对象流的机制,即将对象的内容流化,将数据分解成字节流,以便存储在文件中或用于在网络中传输,可是开发人员在开发经常会遇到java序列化失败,这是什么原因?下面我们就讲解一下。
1.对象序列化错误
一般发生在改完实体类后,然后你redis又忘记清缓存,导致与现有代码中的实体类产生冲突,产生序列化错误。flushdb即可。或者是你改变了某个jar包中的api类,该jar包又被多个进程所引用,而你只替换了某个进程,这也是一个原因。
2.字段序列化错误
1)下面该写法在跨进程时会产生序列化问题。可用谷歌的方法Lists.newArrayList("a","b");替代。
Listlist = new ArrayList() { { add("a"); add("b"); } };
2)当使用如下代码复制一个list时可能会将原先的ArrayList类型给改变成RegularlmmutableAsList或是Single...List(具体类型突然给忘了,反正巨坑),可能还会有更多奇奇怪怪的类型,导致在将数据跨进程传输回去时会产生序列化问题。
3)ArrayList.subList()的结果是subList对象,不能被反序列化。
java序列化缺陷有哪些?
我们在用过的RPC通信框架中,很少会发现使用JDK提供的序列化,主要是因为JDK默认的序列化存在着如下一些缺陷:无法跨语言、易被攻击、序列化后的流太大、序列化性能太差等。
1. 无法跨语言
现在很多系统的复杂度很高,采用多种语言来编码,而Java序列化目前只支持Java语言实现的框架,其它语言大部分都没有使用Java的序列化框架,也没有实现Java序列化这套协议,因此,如果两个基于不同语言编写的应用程序之间通信,使用Java序列化,则无法实现两个应用服务之间传输对象的序列化和反序列化。
2. 易被攻击
Java官网安全编码指导方针里有说明,“对于不信任数据的反序列化,从本质上来说是危险的,应该避免“。可见Java序列化并不是安全的。
我们知道对象是通过在 ObjectInputStream 上调用 readObject() 方法进行反序列化的,这个方法其实是一个神奇的构造器,它可以将类路径上几乎所有实现了 Serializable 接口的对象都实例化。这也就意味着,在反序列化字节流的过程中,该方法可以执行任意类型的代码,这是非常危险的。
对于需要长时间进行反序列化的对象,不需要执行任何代码,也可以发起一次攻击。攻击者可以创建循环对象链,然后将序列化后的对象传输到程序中反序列化,这种情况会导致 hashCode 方法被调用次数呈次方爆发式增长, 从而引发栈溢出异常。
出现java序列化失败的原因可能就是以上三种,如果出现找到解决方法就可以了,另外,java序列化是有缺陷的,所以建议大家能不用序列化就不用哦!最后大家如果想要了解更多java常见问题知识,敬请关注奇Q工具网。
推荐阅读: