序列化可以应用于远程服务间的通信,server端将响应对象进行序列化处理,然后形成二进制流,进行压缩后输出至客户端,本文主要讨论的是一个对象是如何被序列化的,根据在这个流程中所做的动作,我们可以逆推出如何对序列化后的对象,进行反序列化,识别出是哪个对象,该对象的成员变量,有哪些,这些成员变量是否也是参与了序列化等。
ObjectOutputStream:
用途:存放被序列化的对象的:类名(package+ClassName)、SerializableID、序列化类型标志位、成员变量的数目、变量名字、变量类型等
ObjectStreamClass
用途:
程序调用ObjectOutputStream.writeObject方法以后,会先生成该对象,官方的描述是:‘Serialization's descriptor for classes’,某个类的序列化描述信息,有哪些信息呢关于一个待序列化的类:类名、是否是代理、是否是枚举类型、序列化的方式(externalizable 或者serializable)、superDesc(超类的描述信息)、SerializableID、fields集合、构造函数cons等
ObjectStreamField
上面会说到ObjectStreamClass类会包含fields集合,其实就是ObjectStreamField的数组集合,这个类是做什么用的呢?用于存放成员变量的名称、类型等信息。
序列化简化流程:
1、序列化接口调用writeObject
2、生成ObjectStreamClass,如果有超类则先执行超类
3、序列化类基本信息以字节码存储至ObjectOutputStream的字节数组
4、成员变量的值序列化,重复执行步骤2和3、4,直至该成员变量没有下一级成员变量或者VALUE值为null,则完成序列化
综上所述,如果能够清楚的知道一个类的基本信息包括成员变量类型、数量、value值(也被参与序列化)构造、类名的信息,不同的是这些信息是以字节存储的,有了这些信息和知道存储规则,则反序列化是可以重新生成这个对象的,反序列化的时候也会调用构造但不是我们通常理解意义上的构造,所调用的构造实现类为sun.reflect.GeneratedSerializationConstructorAccessor1,该构造并不会调用我们的构造函数,关于反序列化相关的总结,下一篇会继续学习