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字符内容
测试序列化对象及反序列化对象
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,表示定义的部分就完成,下面是写入实例的数据
读取对象 readObject :
-
读先取类名,再读取字段总个数
-
加载类名,再根据类名,加载 deserializer,unsafeDeserializer
-
再依次读取input流中每个字段的定义,为每个字段生成FieldDeserializer,用于反序列化,这个字段数组都是有顺序的
-
读取实例内容,就是从类定义那个分隔符后进行读取
-
调用unsafeDeserializer# readObject(this, fields),读取每个字段的内容
-
依次调用 Deserialize字段数组
-
比如第一个是IntFieldDeserializer#readInt,然后调用_unsafe.putInt(obj, _offset, value)设值
-
比如第二个是StringFieldDeserializer#readString,然后调用_unsafe.putObject(obj, _offset, value) 设值