Java序列化:
Java序列化会把要序列化的对象类的元数据和业务数据全部序列化为字节流,而且是把整个继承关系上的东西全部序列化了。它序列化出来的字节流是对那个对象结构到内容的完全描述,包含所有的信息,因此效率较低而且字节流比较大。但是由于确实是序列化了所有内容,所以可以说什么都可以传输,因此也更可用和可靠。
hession序列化:
它的实现机制是着重于数据,附带简单的类型信息的方法。就像Integer a = 1,hessian会序列化成I 1这样的流,I表示int or Integer,1就是数据内容。而对于复杂对象,通过Java的反射机制,hessian把对象所有的属性当成一个Map来序列化,产生类似M className propertyName1 I 1 propertyName S stringValue(大概如此,确切的忘了)这样的流,包含了基本的类型描述和数据内容。而在序列化过程中,如果一个对象之前出现过,hessian会直接插入一个R index这样的块来表示一个引用位置,从而省去再次序列化和反序列化的时间。这样做的代价就是hessian需要对不同的类型进行不同的处理(因此hessian直接偷懒不支持short),而且遇到某些特殊对象还要做特殊的处理(比如StackTraceElement)。而且同时因为并没有深入到实现内部去进行序列化,所以在某些场合会发生一定的不一致,比如通过Collections.synchronizedMap得到的map。
Hessian 序列化和反序列化实现
先聊聊 Java的序列化,Java官方的序列化和反序列化的实现被太多人吐槽,这得归于Java官方序列化实现的方式。
1、Java序列化的性能经常被吐槽。
2、Java官方的序列化后的数据相对于一些优秀的序列化的工具,还是要大不少,比如probuf,这大大影响存储和传输的效率。
3、Java序列化一定需要实现Serializable接口
4、Java序列化的 serialVersionUID 也是个大坑
另外,序列化和反序列化中还需要考虑:跨语言,新旧对象版本兼容,安全,性能。今天主要来说说,Hessian2是如何来解决这些问题的?
一、跨语言:hessian提供了一整套的byte[]的写入规范,这个规范为其他的语言实现hessian的序列化和反序列化提供了可能。
http://hessian.caucho.com/doc/hessian-serialization.html
目前hessian2已经支持了非常多语言,Java,Node,php,Erlang,c#.......
二、新旧对象版本兼容:hessian2将类的描述信息写入byte[]中,以便于在反序列化时候能正常。但是这样就带来了一个问题:序列化后的内容较大。
三、安全,hessian序列化时,会调用writeReplace方法得到一个新的对象,能将对象中的一些值进行加密后在进行序列化。
四、性能:hessian2的序列化在内容的序列化上做了一些优化,hessian2将需要序列化的多个相同的对象只会写入一次,其他用到该对象的只使用对象的引用,而不重新写入对象的描述信息和值信息。但是hessian2在描述信息上写入的信息来兼容动态化的反序列化支持,所以内容相对于一些描述性的序列化工具(thrift,protobuf)来说,在性能上没有优势。
再回到序列化,相对于 Java来说,hessian的序列化从跨语言,新旧对象的版本兼容,安全以及性能方面都做的好,主要体现在:
一、Java的序列化无法跨语言。
二、新旧对象的版本Java可以通过一个serialVersionUID来处理,这就需要开发者关注序列化的几个语义。
三、Java需要实现一个接口才能进行序列化和反序列化,序列化没有进行加解密的接口。
四、Java序列化后的内容比Hessian更大,这不利于序列化本身的性能和网络传输、以及存储的性能。
当然我们还有更加优秀的一些序列化和反序列化的工具,根据不同的使用场景可以自行选择!
对性能敏感,对开发体验要求不高的内部系统。
thrift/protobuf
对开发体验敏感,性能有要求的内外部系统。
hessian2
对序列化后的数据要求有良好的可读性
jackson/gson/xml