首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

java序列化二

2013-07-04 
java序列化2下面我们再看下反序列化FileInputStream fis ?new?FileInputStream(d:\\hessianPerson.txt)

java序列化2

下面我们再看下反序列化

FileInputStream fis =?new?FileInputStream("d:\\hessianPerson.txt");

Hessian2Input hi =new?Hessian2Input(fis);

Person p = (Person) hi.readObject();

和java序列化一样也是readObject方法,这里面有什么呢?

int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read();? //第一个字符,就是tag,此时C,也就是类

case 'C':

????? {

readObjectDefinition(null); //读取类型信息

return readObject();??????????? //读取属性信息,并将属性信息设置到新建的对象中

????? }

读取类型信息也很简单

? private void readObjectDefinition(Class<?> cl)

??? throws IOException

? {

??? String type = readString();

??? int len = readInt();

??? SerializerFactory factory = findSerializerFactory();

??? Deserializer reader = factory.getObjectDeserializer(type, null);

??? Object []fields = reader.createFields(len);

??? String []fieldNames = new String[len];

??? for (int i = 0; i < len; i++) {

????? String name = readString();

?????

??????fields[i] = reader.createField(name);

????? fieldNames[i] = name;

??? }

???

????ObjectDefinition def = new ObjectDefinition(type, reader, fields, fieldNames);

? }

1、??首先读取?类路径

2、??读取属性个数

3、??获得此种类型的反序列化类,此时是UnsafeDeserializer类

4、??读取属性的名称

5、??根据类路径(也就是类类型)和属性的名称,创建一个ObjectDefinition

?

上面基本上就是java和hessian的序列化和发序列化的过程,到这个地方的时候我们比较一下,一个重要的问题,继承的问题

1、??继承的类没有实现序列化接口

Java序列化??在序列化文件中,不存在任何父类的信息,即使已经设置了父类属性的值,也不会被序列化到,在反序列化的过程中,父类字段值就为相应属性的默认值。

Hessian序列化,在序列化文件中,存在的字段,如果设置了父类属性(和子类不重复)的值,会被序列化到文件中,作为子类的属性在用,因此在反序列化中,可以得到这些属性。

2、??继承的类实现了序列化接口

Java序列化?在序列化中,父类的字段和子类的字段是分开的,首先是子类的字段,及其值,然后是父类的类型,字段,值等,因此在反序列化的时候,可以分清父类和子类的值

而在hessian序列化中,可以看到实现和没有实现是没有区别的,还是一样的,忽略了父类的类型,仅仅是将父类的属性和值放到了序列化文件中,在反序列化的时候就分不清父类和子类的值了。这一点有可能造成一些比较麻烦的问题,参考http://jameswxx.iteye.com/blog/1071476??这个应该是我们公司的人遇到的,但是模拟了下,应该还算编码不规范导致的。

----------------------------------------------------hessian序列化完成--------------------------------------------------------

总结下?hessian序列化和java序列化的区别

1、??hessian序列化针对某些特定的类型进行优化,使得这些类型的序列化更快和更小

2、??hessian序列化不管父类有没有序列化,将其当做子类属性来处理。

3、??hessian序列化?在某些情况(编码不规范)下,会有一些小问题。

-----------------------------------------------------fastjson序列化--------------------------------------------------------------------

根据上面的思路,我们来看下fastjson,号称史上最快,序列化结果最小的工具

Person?myPerson =?new?Person();?? myPerson.setAge(10);??? myPerson.setName("wangshiji");

Object text = JSON.toJSONString(myPerson);???? System.out.println(text);

结果为{"age":10,"name":"wangshiji"}

下面分析下代码:

SerializeWriter out = new SerializeWriter();

??????? try {

??????????? JSONSerializer serializer = new JSONSerializer(out);

??????????? for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {

??????????????? serializer.config(feature, true);

??????????? }

??????????? serializer.write(object);

??????????? return out.toString();

??????? } finally {

??????????? out.close();

?????? ?}

根据温少的文章?http://www.iteye.com/topic/1113183??,快的原因之一是自行编写类似StringBuilder的工具类SerializeWriter,仔细的看了下,没有发现提高性能的方式,不过这句话也是对的public void writeIntAndChar(int i, char c) {},这样的方法一次性把两个值写到buf中去,能够减少一次越界检查。呵呵。使用ThreadLocal来缓存buf。这个确实能提高性能,因为StringBuffer有synchronized标示符,而StringBuilder不是线程安全的,但是由于用的是软引用,有可能在GC的时候,将其回收也是一个问题。

下面我们来分析serializer.write(object);??这个代码结构

Class<?> clazz = object.getClass();??????????????????? //得到当前类的类型

ObjectSerializer writer = getObjectWriter(clazz);????? //通过类型,得到相应的序列化器

writer.write(this, object,?null,?null);??????????????? //通过相应的序列化器,将object进行序列化

?

跟进去就会发现?这里面会判断?clazz的类型,然后赋予已经定义好的序列化器,比如MapSerializer,ListSerializer。。。等,如果是自定义的pojo怎么办呢?因为不可能将所有的类型都写一遍的,这个地方就体现出fastjson高明的地方了,其实这个问题在hessian中也会遇到,hessian是不管当前类的类型,用类中属性的类型进行序列化,如果属性还是自定义pojo,则进行递归,这个方式是好的,但是fastjson更加高明,通过asm工具?直接根据当前类型,生成了一个序列化器,就是通过这个方法生成的

config.createJavaBeanSerializer(clazz)

至于asm,大家可以看下,还是比较简单的,但是这个生成的过程还是挺复杂的,可以将他那个反射类拿出来,然后在反编译就可以看到原貌了。

简单来说,就是首先得到所有属性类型,然后再调用相应的序列化器将其序列化,思想和hessian一致。如果属性还是自定义pojo,则进行递归。

?

反序列化的内容,就看下上面那篇文章吧,http://www.iteye.com/topic/1113183,有很多料的

?

?

热点排行