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.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.4、否则,构造一个JavaSerializer并返回
        • 1.13.4.1、如果目标类设置了注解HessianUnshared(不检测重复或循环引用),构造一个JavaUnsharedSerializer并返回
        • 1.13.4.2、否则,构造一个JavaSerializer并返回
    • 1.4、将得到的序列化器放入缓存

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

java hessian