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、解析时读取对象类型,以返回的数据中指定的类型为准