hessian序列化与反序列化过程分析

113 阅读2分钟

hessian序列化与反序列化过程分析

​ dubbo默认都是采用hessian2进行序列化与反序列化操作 ​ 下面从一个简单的例子说

public class PojoDemo implements Serializable {

    private String name;

    private String addr;

    private int   age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

​ 这里有引用了dubbo的测试类

class Hessian2SerializationTest {
    @Test
    void testReadString() throws IOException, ClassNotFoundException {
        FrameworkModel frameworkModel = new FrameworkModel();
        Serialization serialization =
                frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
        URL url = URL.valueOf("").setScopeModel(frameworkModel);

        // write string, read string
        {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ObjectOutput objectOutput = serialization.serialize(url, outputStream);
            objectOutput.writeObject("hello");
            objectOutput.writeObject(pojoDemo);
           objectOutput.writeInt(42);
            objectOutput.writeObject("test");
            objectOutput.flushBuffer();

            byte[] bytes = outputStream.toByteArray();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
            ObjectInput objectInput = serialization.deserialize(url, inputStream);
            Object object = objectInput.readObject();

            Assertions.assertEquals("hello", objectInput.readUTF());
        }
  • 当objectOutput.writeObject("hello")时,第0号位置表示长度,这里长度为5,1-5分别表示hello的 每个字符
  • 再写入robin字符内容

6396.png

测试序列化对象及反序列化对象
class Hessian2SerializationTest {
    @Test
    void testReadString() throws IOException, ClassNotFoundException {
        FrameworkModel frameworkModel = new FrameworkModel();
        Serialization serialization =
                frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
        URL url = URL.valueOf("").setScopeModel(frameworkModel);

        // write string, read string
        {
           
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ObjectOutput objectOutput = serialization.serialize(url, outputStream);
            PojoDemo pojoDemo=new PojoDemo();
            pojoDemo.setAddr("hncn");
            pojoDemo.setAge(22);
            pojoDemo.setName("hello1");
            objectOutput.writeObject(pojoDemo);
            objectOutput.flushBuffer();

            byte[] bytes = outputStream.toByteArray();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
            ObjectInput objectInput = serialization.deserialize(url, inputStream);
            Object object = objectInput.readObject();

            Assertions.assertEquals("hello", objectInput.readUTF());
        }
写入对象 objectOutput.writeObject;
  • 第一步,写入类名,0号位置是类的标识67,即“C”字符,然后写入类名长度,接着是写入类名具体字节

  • 第二步,写入类的字段总数量

  • 第三步,写入每个字段的名称字符串长度,及字符串名称内容

  • 第四步,写入一个标识BC_OBJECT_DIRECT,表示定义的部分就完成,下面是写入实例的数据

88160.png

读取对象 readObject
  • 读先取类名,再读取字段总个数

  • 加载类名,再根据类名,加载 deserializer,unsafeDeserializer

  • 再依次读取input流中每个字段的定义,为每个字段生成FieldDeserializer,用于反序列化,这个字段数组都是有顺序的

  • 读取实例内容,就是从类定义那个分隔符后进行读取

  • 调用unsafeDeserializer# readObject(this, fields),读取每个字段的内容

  • 依次调用 Deserialize字段数组

  • 比如第一个是IntFieldDeserializer#readInt,然后调用_unsafe.putInt(obj, _offset, value)设值

  • 比如第二个是StringFieldDeserializer#readString,然后调用_unsafe.putObject(obj, _offset, value) 设值