(反)序列化

标签: 序列化 | 发表时间:2014-11-24 23:07 | 作者:逆天子军少
出处:http://www.iteye.com

本章关注对象序列化API,它提供了一个框架,用来将对象编码成字节流,并从字节流中重新构建对象。“将对象编码成字节流”被称作对象序列化,相反的处理过程被称作反序列化。序列化技术为远程通信提供了标准的线路级对象表示法,也为JavaBeans组件结构提供了标准的持久化数据格式。

 

第七十四条:谨慎地实现Serializable接口

实现Serializable接口而付出的最大代价是,一旦一个类发布,就大大降低了“改变这个类实现”的灵活性。序列化会使类的演变受到限制,这与流的唯一标识符有关,通常它也被称为序列版本UID。每个可序列化的类都有一个唯一标识符与它相关联。如果你没有显示指定该标志号,系统就会自动根据这个类的名称,所实现接口的名称等计算出一个标志号。如果你改变了类,比如增加了一个工具方法,自动产生的UID会产生变化。因此,如果你没有显示声明UID,兼容性将遭到破坏。

第二个代价是,它增加了出现Bug和安全漏洞的可能性。序列化机制是一种语言之外的对象创建机制。反序列化是一个隐藏的构造器,具备和其他构造器相同的特点。所以要确保:反序列化过程必须要保证所有“由真正的构造器建立起来的约束关系”,并且不允许攻击者访问正在构造过程中的对象的内部信息。依靠默认的反序列化机制,很容易使对象的约束关系遭到破坏,以及遭到非法访问。

第三个代价,随着类发行新的版本,相关的测试负担也增加了。

根据经验,比如Date和BigInteger这样的值类应该实现Serializable,大多数的集合也应如此。代表活动实体的类比如线程池,一般不实现。

 

第七十五条:考虑使用自定义的序列化形式

如果一个对象的物理表示法等同于它的逻辑内容,可能就适合使用默认的序列化形式。即使你确认了默认的序列化形式是合适的,通常还必须提供一个readObject方法以保证约束关系和安全性。

当一个对象的物理表示法和逻辑数据内容有实质性的区别时,使用默认序列化形式会有下面四个缺点:

1.它使这个类的导出API永远的束缚在该类的内部表示法上。

2.消耗过多的空间。

3.消耗过多的时间。

4.引起栈溢出。

自定义序列化形式通常自定义writeObject和readObject方法,用来序列化和反序列化。同时,使用transient修饰符使实例域从一个类的默认序列化形式中省略掉。

 

第七十六条:保护性的编写readObject方法

不严格地说,readObject是一个“用字节流作为唯一参数”的构造器。在正常使用的情况下,对一个正常构造的实例进行序列化可以产生字节流。但是,当面对一个人工仿造的字节流时,readObject产生的对象可能会违反所属的类的约束条件。

为了解决这个问题,可以为实现默认序列化的类添加一个readObject方法,该方法首先调用defaultReadObject,然后检查被反序列化之后对象的有效性。但这样仍可能解决不了问题,攻击者可以使用对象引用来修改实例的内部组件。 当一个对象被反序列化的时候,对于客户端不应该拥有的对象应用,如果哪个域包含了这样的对象引用,就必须要做保护性拷贝。并且,保护性拷贝是在有效性检查之前进行。

下面的建议有利于编写更加健壮的readObject方法:

1.对于对象引用域必须保持为私有的类,要保护性地拷贝这些域中的每个对象。不可变类的可变组件就属于这一类别。

2.对于任何约束条件,如果检查失败,抛出InvalidObjectException异常。这些检查跟在所有保护性拷贝之后。

3.如果整个对象在被反序列化之后必须进行验证,就应该使用ObjectInputValidation接口

4.不要调用类中可能被覆盖的方法。

 

第七十七条:对于实例控制,枚举类型优先于readResolve

readResolve特性允许你用readObject创建的实例代替另一个实例。对于一个正在被反序列化的对象,如果他的类定义了一个readResolve方法,并且具备正确的声明,那么在反序列化之后,新建对象上的readResolve方法就会被调用。然后该方法返回的对象引用被返回,取代新建的对象。

尽可能使用枚举类型来实施实例控制的约束条件。如果做不到,同时又需要一个既可序列化又是实例受控的类,就必须提供一个readResolve方法,并确保该类的所有实例域都为基本类型或者是transient的。

 

第七十八条:考虑用序列化代理代替序列化实例

序列化代理模式相当简单。首先,为可序列化的类设计一个私有的静态嵌套类,精确地表示外围类的实例的逻辑状态。这个嵌套类被称作序列化代理,它应该有一个单独的构造器,其参数类型就是那个外围类。这个构造器只从它的参数中复制数据:他不需要进行任何一致性检查或者保护性拷贝。从设计的角度看,序列化代理的默认序列化形式是外围类最好的序列化形式。外围类及其序列代理都必须声明Serializable接口。

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [序列化] 推荐:

(反)序列化

- - Java - 编程语言 - ITeye博客
本章关注对象序列化API,它提供了一个框架,用来将对象编码成字节流,并从字节流中重新构建对象. “将对象编码成字节流”被称作对象序列化,相反的处理过程被称作反序列化. 序列化技术为远程通信提供了标准的线路级对象表示法,也为JavaBeans组件结构提供了标准的持久化数据格式. 第七十四条:谨慎地实现Serializable接口.

java序列化java.io.Externalizable

- - Java - 编程语言 - ITeye博客
这次我们讲的是控制对象的序列化和反序列化. 控制序列化就是有选择的序列化对象,而不是把对象的所以内容都序列化,前篇我们的例子中介绍了transit变量和类变量(static)不被序列化,现在我们还有一种更为灵活的控制对象序列化和反序列方法,可以在序列化过程中储存其他非this对象包含的数据. 我们现在再来介绍一个接口 java.io.Externalizable.

java序列化与反序列化以及浅谈一下hadoop的序列化

- - CSDN博客云计算推荐文章
1、什么是序列化和反序列化. 神马是序列化呢,序列化就是把 内存中的对象的状态信息,转换成 字节序列以便于存储(持久化)和网络传输. (网络传输和硬盘持久化,你没有一定的手段来进行辨别这些字节序列是什么东西,有什么信息,这些字节序列就是垃圾). 反序列化就是将收到 字节序列或者是硬盘的持久化数据,转换成 内存中的对象.

JAVA 反序列化攻击

- - OneAPM 博客
Java 反序列化攻击漏洞由. FoxGlove 的最近的一篇博文爆出,该漏洞可以被黑客利用向服务器上传恶意脚本,或者远程执行命令. 由于目前发现该漏洞存在于 Apache commons-collections, Apache xalan 和 Groovy 包中,也就意味着使用了这些包的服务器(目前发现有WebSphere, WebLogic,JBoss),第三方框架(Spring,Groovy),第三方应用(Jenkins),以及依赖于这些服务器,框架或者直接/间接引用这些包的应用都会受到威胁,这样的应用的数量会以百万计.

使用SerializableAttribute进行对象序列化与反序列化

- - CSDN博客推荐文章
SerializableAttribute属性用于修饰可以序列化的类,如果类支持序列化,便可以使用该属性来修饰. 需要注意的并不是所有支持序列化的类都需要被SerializableAttribute来修饰,只有该类需要或可能需要序列化时,如一些实体类,可能需要持久化或用于进程间传输. 这样的对象需要被序列化成字节流或其它便于存储或传输的格式,并且通过这个持久化的格式可以还原或反序列化至内存.

讲解Java中的序列化

- - IT江湖
serialVersionUID的作用. serialVersionUID适用于JAVA的序列化机制. 简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的. 在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException.

理解Java对象序列化

- - 博客 - 伯乐在线
来源: jiangshapub 的博客( @jiangshapub). 关于Java序列化的文章早已是汗牛充栋了,本文是对我个人过往学习,理解及应用Java序列化的一个总结. 此文内容涉及Java序列化的基本原理,以及多种方法对序列化形式进行定制. 在撰写本文时,既参考了 Thinking in Java, Effective Java,JavaWorld,developerWorks中的相关文章和其它网络资料,也加入了自己的实践经验与理解,文、码并茂,希望对大家有所帮助.

对Java序列化早作防备(译)

- - BlogJava_首页
本文是 IBM developerWorks中的 一篇文章,介绍了不使用加密与签章技术,如何防止对不可信数据输入的解序列化. (2013.01.17最后更新).     Java序列化允许开发者将Java对象保存为二进制格式,以便将该对象持久化到一个文件中或将其在网络中进行传递. 远程方法调用(RMI)使用序列化作为客户端与服务器端之间的通信媒介.

java 序列化 serializable接口 serialVersionUID

- - 互联网 - ITeye博客
如果一个类实现了serializable接口,那么就会要求一个serialVersionUID. 序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类. 如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException.

高性能序列化框架FST

- - 开源软件 - ITeye博客
fst是完全兼容JDK序列化协议的系列化框架,序列化速度大概是JDK的4-10倍,大小是JDK大小的1/3左右. System.out.println("序列化 , 反序列化 对比测试:");. System.out.println("原生序列化方案[序列化10000次]耗时:". System.out.println("fst序列化方案[序列化10000次]耗时:".