hessian 序列化和反序列化
hessian请求代理
com.caucho.hessian.client.HessianProxy.invoke(Object proxy, Method method, Object []args); // 通过代理方式调用远程方法,并返回结果
com.caucho.hessian.io.Hessian2Input.readReply(Class expectedClass); // 读取返回结果 readObject(Class cl); // 读取一个类对象
序列化器查找流程
- 1、通过
SerializerFactory.getObjectSerializer(object.getClass()),获取目标对象的序列化器- 1.1、调用
SerializerFactory.getSerializer(Class cl)获取目标类的序列化器 - 1.2、如果
_cachedSerializerMap缓存中有,则取缓存的序列化器 - 1.3、如果缓存没有,调用
SerializerFactory.loadSerializer(Class<?> cl)获取目标类的序列化器 - 1.4、遍历
SerializerFactory._factories(自行添加的序列化器工厂),如果有一个工厂提供目标类的序列化器,就采用该工厂提供的序列化器 - 1.5、否则(1.4),调用
SerializerFactory初始化时构造的上下文序列化工厂ContextSerializerFactory.getSerializer(Class cl)查询序列化器,如果找到,就采用 - 1.6、否则(1.5),就使用
目标类的类加载器构造ContextSerializerFactory,并通过该序列化工厂的getCustomSerializer()查询序列化器,如果找到,就采用- 1.6.1、
Class.forName(cl.getName() + "HessianSerializer", false, cl.getClassLoader())获取序列化器
- 1.6.1、
- 1.7、否则(1.6),如果目标类是
com.caucho.hessian.io.HessianRemoteObject类型或其子类,返回com.caucho.hessian.io.RemoteSerializer - 1.8、否则(1.7),如果目标类是
com.caucho.burlap.io.BurlapRemoteObject类型或其子类,返回com.caucho.hessian.io.RemoteSerializer - 1.9、否则(1.8),如果目标类拥有名为
writeReplace的无参方法,就根据该方法构造一个WriteReplaceSerializer返回 - 1.10、否则(1.9),如果目标类是
Map,返回MapSerializer(懒加载) - 1.11、否则(1.10),如果目标类是
Collection,返回CollectionSerializer* (懒加载) - 1.12、否则(1.11),
Array、InputStream、Iterator、Calendar、* Enumeration、Enum、Annotation分别返回对应的内置序列化器 - 1.13、否则(1.12),调用
SerializerFactory.getDefaultSerializer(Class cl)返回默认的序列化器- 1.13.1、如果
_defaultSerializer不为空,就采用 - 1.13.2、如果目标类型未实现
Serializable接口,且设置了禁止‘不支持序列化的类’的状态_isAllowNonSerializable,将跑出异常IllegalStateException - 1.13.3、如果启用了不安全的序列化器,并且目标类没有名为
writeReplace的无参方法,就构造一个UnsafeSerializer并返回- 1.13.3.1、如果目标类设置了注解
HessianUnshared(不检测重复或循环引用),构造一个UnsafeUnsharedSerializer并返回 - 1.13.3.2、否则,构造一个
UnsafeSerializer并返回
- 1.13.3.1、如果目标类设置了注解
- 1.13.4、否则,构造一个
JavaSerializer并返回- 1.13.4.1、如果目标类设置了注解
HessianUnshared(不检测重复或循环引用),构造一个JavaUnsharedSerializer并返回 - 1.13.4.2、否则,构造一个
JavaSerializer并返回
- 1.13.4.1、如果目标类设置了注解
- 1.13.1、如果
- 1.4、将得到的序列化器放入缓存
- 1.1、调用
JavaSerializer 和 UnsafeSerializer 的区别:
JavaSerializer:通过反射机制获取字段值
UnsafeSerializer:通过sun.misc.Unsafe获取字段的值
反序列化过程
1、使用InputStream构造AbstractHessianInput对象
2、调用AbstractHessianInput.readReply(Class expectedClass)读取一个响应对象
3、如果tag='R',调用readObject(Class cl)读取一个对象
4、readObjectDefinition(Class<?> cl)读取一个对象定义
4.1、SerializerFactory.getObjectDeserializer(String type, Class cl)获取一个反序列化器,如果cl为null 或 cl和序列化器支持的类型一致 等情况直接使用该反序列化器
4.1.1、SerializerFactory.getObjectDeserializer(String type)获取一个反序列化器
4.1.1.1、SerializerFactory.getDeserializer(String type)获取一个反序列化器
4.1.1.1.1、如果type为[开头,就构造一个数组反序列化器,数组内容,使用type.substring(1),作为参数调用本方法获取。
4.1.1.1.2、否则通过反射Class.forName得到type对应的实体类,然后使用得到的实体类调用SerializerFactory.getDeserializer(Class cl)获取一个反序列化器
4.2、如果4.1.1得到的反序列化器不符合要求,就调用SerializerFactory.getDeserializer(Class cl)获取一个反序列化器
4.2.1、调用SerializerFactory.loadDeserializer(Class cl)获取一个反序列化器
4.2.1.1、遍历 SerializerFactory._factories(自行添加的序列化器工厂),如果有一个工厂提供目标类的反序列化器,就采用该工厂提供的反序列化器
4.2.1.2、调用 SerializerFactory 初始化时构造的上下文序列化工厂 ContextSerializerFactory.getDeserializer(String className) 查询序反列化器,如果找到,就采用
4.2.1.3、使用目标类的类加载器构造 ContextSerializerFactory,并通过该序列化工厂的getCustomDeserializer()查询序列化器,如果找到,就采用
4.2.1.4、Collection、Map、Iterator、Annotation、Interface(使用ObjectDeserializer)、Array、Enumeration、Enum、Class都有内置对应的反序列化器
4.2.1.5、调用SerializerFactory.getDefaultDeserializer(Class cl)返回默认的序列化器
4.2.1.5.1、如果目标类型为InputStream,使用InputStreamDeserializer.DESER作为反序列化器
4.2.1.5.2、如果启用了不安全的序列化器,使用UnsafeDeserializer(cl)
4.2.1.5.2.1、如果目标类型有名为readResolve的无参方法,标记_readResolve.setAccessible(true)
4.2.1.5.3、否则,使用JavaDeserializer(cl)
4.2.1.5.3.1、如果目标类型有名为readResolve的无参方法,标记_readResolve.setAccessible(true)
5、readObjectInstance(Class<?> cl, ObjectDefinition def)根据上一步的结果读取一个对象实例
特殊问题
客户端与服务端字段不一致
1、客户端多一个字段,该字段取JVM默认值 2、客户端缺失字段,该字段不解析 3、解析时读取对象类型,以返回的数据中指定的类型为准