golang实现Java序列化/反序列化

17 篇文章 0 订阅
本文深入剖析了Java序列化算法的工作原理,包括文件头、类描述符、数据部分的解析,并通过示例展示了如何处理ArrayList、HashMap等复杂类型的序列化。此外,还介绍了GitHub上的Husky项目,它能实现Java类与GoStruct之间的直接转换,为跨语言的数据交换提供了便利。
摘要由CSDN通过智能技术生成

首先上github项目地址(基本可以直接将go struct直接与java class互转,觉得可以的大家给颗星https://github.com/qauzy/huskyicon-default.png?t=M276https://github.com/qauzy/husky项目源于GitHub - davidwang2007/golang-java-serializer: golang library for handle java serialization/deserializationgolang library for handle java serialization/deserialization - GitHub - davidwang2007/golang-java-serializer: golang library for handle java serialization/deserializationhttps://github.com/davidwang2007/golang-java-serializer

Java序列化算法:

java的序列化算法看起来比较简单,

1 首先是序列化文件头,接着是类描述符,接着父类的描述符(如果存在),直至没有父类。

2 接着是数据部分,从父类的成员数据开始,如果成员数据是Object类型还需要先写入该Object类的描述符,接着才是数据

3 对于ArrayList,HashMap等类型自带了序列化方法,需要执行特殊序列化

具体过程可以看下面github中例子的解析过程

第一部分是序列化文件头
0xACED: magic  声明使用了序列化协议.
0x05:   version 序列化协议版本.
0x73:   TC_OBJECT. 声明这是一个新的对象.

按顺序获取类描述,类数据块信息,获取第[0]块信息
第二部分是序列化的类的描述[深度:0]

0x72: TC_CLASSDESC. 声明这里开始一个新Class
0x21: 类名字的长度[33]
0x636F6D2E6578616D706C652E64656D6F2E6D6F64656C2E55736572456E74697479: 尝试读取类名[com.example.demo.model.UserEntity]
0x48B027EB0BF53976: SerialVersionUID,序列化ID,如果没有指定,则会由算法随机生成一个8byte的ID.
[添加] [引用] [0] 类型:TC_CLASSDESC[0x72], refVal:{"ClassName":"com.example.demo.model.UserEntity","ScFlag":0,"SerialVersionUID":5237730257103305078,"Fields":null,"RwDatas":null}      
0x02: 标记号. 该值声明该对象支持序列化
0x08: 该类[com.example.demo.model.UserEntity]所包含的域个数,有8个成员

第三部分是类[com.example.demo.model.UserEntity]中各个属性的描述
准备解析类[com.example.demo.model.UserEntity]第1个属性

0x4C: 成员类型[L]
0x05: 成员名字长度
0x6769667473: 成员名字[gifts]
0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x15: 该TC_STRING的长度[21]
0x4C6A6176612F7574696C2F41727261794C6973743B: 字符串原文:Ljava/util/ArrayList;
[添加] [引用] [1] 类型:TC_STRING[0x74], refVal:"Ljava/util/ArrayList;"
类[com.example.demo.model.UserEntity]第1个属性 :type: 0x4C, name: gifts, flag: 0x2, class: Ljava/util/ArrayList;

准备解析类[com.example.demo.model.UserEntity]第2个属性
0x5B: 成员类型[[]
0x06: 成员名字长度
0x676966747332: 成员名字[gifts2]
0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x13: 该TC_STRING的长度[19]
0x5B4C6A6176612F6C616E672F537472696E673B: 字符串原文:[Ljava/lang/String;
[添加] [引用] [2] 类型:TC_STRING[0x74], refVal:"[Ljava/lang/String;"
类[com.example.demo.model.UserEntity]第2个属性 :type: 0x5B, name: gifts2, flag: 0x2, class: [Ljava/lang/String;

准备解析类[com.example.demo.model.UserEntity]第3个属性
0x4C: 成员类型[L]
0x02: 成员名字长度
0x6964: 成员名字[id]
0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x10: 该TC_STRING的长度[16]
0x4C6A6176612F6C616E672F4C6F6E673B: 字符串原文:Ljava/lang/Long;
[添加] [引用] [3] 类型:TC_STRING[0x74], refVal:"Ljava/lang/Long;"
类[com.example.demo.model.UserEntity]第3个属性 :type: 0x4C, name: id, flag: 0x2, class: Ljava/lang/Long;

准备解析类[com.example.demo.model.UserEntity]第4个属性
0x4C: 成员类型[L]
0x06: 成员名字长度
0x6F7468657273: 成员名字[others]
0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x13: 该TC_STRING的长度[19]
0x4C6A6176612F7574696C2F486173684D61703B: 字符串原文:Ljava/util/HashMap;
[添加] [引用] [4] 类型:TC_STRING[0x74], refVal:"Ljava/util/HashMap;"
类[com.example.demo.model.UserEntity]第4个属性 :type: 0x4C, name: others, flag: 0x2, class: Ljava/util/HashMap;

准备解析类[com.example.demo.model.UserEntity]第5个属性
0x4C: 成员类型[L]
0x07: 成员名字长度
0x6F746865727332: 成员名字[others2]
0x71: TC_REFERENCE 标识引用
0x7E0004: TC_REFERENCE引用序号[4]
类[com.example.demo.model.UserEntity]第5个属性 :type: 0x4C, name: others2, flag: 0x2, class: Ljava/util/HashMap;

准备解析类[com.example.demo.model.UserEntity]第6个属性
0x4C: 成员类型[L]
0x03: 成员名字长度
0x736F6E: 成员名字[son]
0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x22: 该TC_STRING的长度[34]
0x4C636F6D2F6578616D706C652F64656D6F2F6D6F64656C2F536F6E456E746974793B: 字符串原文:Lcom/example/demo/model/SonEntity;
[添加] [引用] [5] 类型:TC_STRING[0x74], refVal:"Lcom/example/demo/model/SonEntity;"
类[com.example.demo.model.UserEntity]第6个属性 :type: 0x4C, name: son, flag: 0x2, class: Lcom/example/demo/model/SonEntity;

准备解析类[com.example.demo.model.UserEntity]第7个属性
0x4C: 成员类型[L]
0x08: 成员名字长度
0x757365724E616D65: 成员名字[userName]
0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x12: 该TC_STRING的长度[18]
0x4C6A6176612F6C616E672F537472696E673B: 字符串原文:Ljava/lang/String;
[添加] [引用] [6] 类型:TC_STRING[0x74], refVal:"Ljava/lang/String;"
类[com.example.demo.model.UserEntity]第7个属性 :type: 0x4C, name: userName, flag: 0x2, class: Ljava/lang/String;

准备解析类[com.example.demo.model.UserEntity]第8个属性
0x4C: 成员类型[L]
0x07: 成员名字长度
0x75736572536578: 成员名字[userSex]
0x71: TC_REFERENCE 标识引用
0x7E0006: TC_REFERENCE引用序号[6]
类[com.example.demo.model.UserEntity]第8个属性 :type: 0x4C, name: userSex, flag: 0x2, class: Ljava/lang/String;

0x78: TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕
按顺序获取类描述,类数据块信息,获取第[1]块信息
第四部分为对象的父类信息描述
第二部分是序列化的类的描述[深度:1]

0x72: TC_CLASSDESC. 声明这里开始一个新Class
0x21: 类名字的长度[33]
0x636F6D2E6578616D706C652E64656D6F2E6D6F64656C2E42617365456E74697479: 尝试读取类名[com.example.demo.model.BaseEntity]
0x01: SerialVersionUID,序列化ID,如果没有指定,则会由算法随机生成一个8byte的ID.
[添加] [引用] [7] 类型:TC_CLASSDESC[0x72], refVal:{"ClassName":"com.example.demo.model.BaseEntity","ScFlag":0,"SerialVersionUID":1,"Fields":null,"RwDatas":null}
0x02: 标记号. 该值声明该对象支持序列化
0x01: 该类[com.example.demo.model.BaseEntity]所包含的域个数,有1个成员

第三部分是类[com.example.demo.model.BaseEntity]中各个属性的描述
准备解析类[com.example.demo.model.BaseEntity]第1个属性

0x4C: 成员类型[L]
0x08: 成员名字长度
0x626173654E616D65: 成员名字[baseName]
0x71: TC_REFERENCE 标识引用
0x7E0006: TC_REFERENCE引用序号[6]
类[com.example.demo.model.BaseEntity]第1个属性 :type: 0x4C, name: baseName, flag: 0x2, class: Ljava/lang/String;
0x78: TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕

按顺序获取类描述,类数据块信息,获取第[2]块信息
0x70: TC_NULL,标记后面的数据为空,説明已经没有父类信息了[深度:2]

[添加] [引用] [8] 类型:TC_OBJECT[0x73], refVal:{"Classes":[{"ClassName":"com.example.demo.model.UserEntity","ScFlag":2,"SerialVersionUID":5237730257103305078,"Fields":[{"FieldType":76,
"FieldName":"gifts","FieldOwnerScFlag":2,"FieldObjectClassName":"Ljava/util/ArrayList;","FieldValue":null},{"FieldType":91,"FieldName":"gifts2","FieldOwnerScFlag":2,"FieldObjectClassNa
me":"[Ljava/lang/String;","FieldValue":null},{"FieldType":76,"FieldName":"id","FieldOwnerScFlag":2,"FieldObjectClassName":"Ljava/lang/Long;","FieldValue":null},{"FieldType":76,"FieldNa
me":"others","FieldOwnerScFlag":2,"FieldObjectClassName":"Ljava/util/HashMap;","FieldValue":null},{"FieldType":76,"FieldName":"others2","FieldOwnerScFlag":2,"FieldObjectClassName":"Lja
va/util/HashMap;","FieldValue":null},{"FieldType":76,"FieldName":"son","FieldOwnerScFlag":2,"FieldObjectClassName":"Lcom/example/demo/model/SonEntity;","FieldValue":null},{"FieldType":
76,"FieldName":"userName","FieldOwnerScFlag":2,"FieldObjectClassName":"Ljava/lang/String;","FieldValue":null},{"FieldType":76,"FieldName":"userSex","FieldOwnerScFlag":2,"FieldObjectCla
ssName":"Ljava/lang/String;","FieldValue":null}],"RwDatas":null},{"ClassName":"com.example.demo.model.BaseEntity","ScFlag":2,"SerialVersionUID":1,"Fields":[{"FieldType":76,"FieldName":
"baseName","FieldOwnerScFlag":2,"FieldObjectClassName":"Ljava/lang/String;","FieldValue":null}],"RwDatas":null}],"SerialVersionUID":0,"JsonData":null,"RawData":null}

第五部分数据信息(类成员值),从父类的Field反序列化[com.example.demo.model.UserEntity]
第五部分数据信息(类成员值),从父类的Field反序列化[com.example.demo.model.BaseEntity]->分解动作
尝试获取第[1]个类(可序列化)[com.example.demo.model.BaseEntity]-->第[0]个成员[baseName]值

************************BEGIN[baseName]************************
解析对象类型类成员[baseName]
0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x04: 该TC_STRING的长度[4]
0x62617365: 字符串原文:base
[添加] [引用] [9] 类型:TC_STRING[0x74], refVal:"base"

************************END[baseName]************************
第五部分数据信息(类成员值),从父类的Field反序列化[com.example.demo.model.UserEntity]->分解动作
尝试获取第[0]个类(可序列化)[com.example.demo.model.UserEntity]-->第[0]个成员[gifts]值
************************BEGIN[gifts]************************

解析对象类型类成员[gifts]
[ReadTcObjFieldValue]解析类对象

0x73: TC_OBJECT. 声明这是一个新的对象(未被消费)
按顺序获取类描述,类数据块信息,获取第[0]块信息
第二部分是序列化的类的描述[深度:0]

0x72: TC_CLASSDESC. 声明这里开始一个新Class
0x13: 类名字的长度[19]
0x6A6176612E7574696C2E41727261794C697374: 尝试读取类名[java.util.ArrayList]
0x7881D21D99C7619D: SerialVersionUID,序列化ID,如果没有指定,则会由算法随机生成一个8byte的ID.
[添加] [引用] [10] 类型:TC_CLASSDESC[0x72], refVal:{"ClassName":"java.util.ArrayList","ScFlag":0,"SerialVersionUID":8683452581122892189,"Fields":null,"RwDatas":null}
0x03: 标记号. 拥有自己的writeObject, readObject, for example: HashMap, 此种类型需要每一个定义一个相应的结构体
0x01: 该类[java.util.ArrayList]所包含的域个数,有1个成员

第三部分是类[java.util.ArrayList]中各个属性的描述
准备解析类[java.util.ArrayList]第1个属性

0x49: 成员类型[I]
0x04: 成员名字长度
0x73697A65: 成员名字[size]
类[java.util.ArrayList]第1个属性 :type: 0x49, name: size, flag: 0x3, class:
0x78: TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕

按顺序获取类描述,类数据块信息,获取第[1]块信息
0x70: TC_NULL,标记后面的数据为空,説明已经没有父类信息了[深度:1]
[添加] [引用] [11] 类型:TC_OBJECT[0x73], refVal:{"Classes":[{"ClassName":"java.util.ArrayList","ScFlag":3,"SerialVersionUID":8683452581122892189,"Fields":[{"FieldType":73,"FieldName":"
size","FieldOwnerScFlag":3,"FieldObjectClassName":"","FieldValue":null}],"RwDatas":null}],"SerialVersionUID":0,"JsonData":null,"RawData":null}

第五部分数据信息(类成员值),从父类的Field反序列化[java.util.ArrayList]
第五部分数据信息(类成员值),从父类的Field反序列化[java.util.ArrayList]->分解动作
尝试获取第[0]个类(自定义序列化)[java.util.ArrayList]
************************BEGIN************************
[JavaArrayList] >>
=================Blockdata数据块起始位置=================

0x04:   Blockdata数据块大小[4]
0x77:   在对象的WriteObject方法中,我们可以自定义的写入数据,除了非Object数据,其他所有数据将会被写在一起,也就是BlockData
0x04:   固定为0x04
0x04:   数组元素的个数

======================读取第1个数据块======================
0x74: TC_STRING.代表一个new String.用String来引用对象(ReadNextEle)
[添加] [引用] [12] 类型:TC_STRING[0x74], refVal:"AAAAA"
======================读取第2个数据块======================
0x71: TC_REFERENCE
0x7E000C: TC_REFERENCE引用序号[12]
======================读取第3个数据块======================
0x74: TC_STRING.代表一个new String.用String来引用对象(ReadNextEle)
[添加] [引用] [13] 类型:TC_STRING[0x74], refVal:"BBBBB"
======================读取第4个数据块======================
0x71: TC_REFERENCE
0x7E000D: TC_REFERENCE引用序号[13]
0x78:   TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕

[JavaArrayList] <<
************************END************************
************************END[gifts]************************

尝试获取第[0]个类(可序列化)[com.example.demo.model.UserEntity]-->第[1]个成员[gifts2]值
************************BEGIN[gifts2]************************
解析数组类型类成员[gifts2]

0x13: 类名字的长度[19]
0x5B4C6A6176612E6C616E672E537472696E673B: 尝试读取类名[[Ljava.lang.String;]
0xADD256E7E91D7B47: SerialVersionUID,序列化ID,如果没有指定,则会由算法随机生成一个8byte的ID.
[添加] [引用] [14] 类型:TC_CLASSDESC[0x72], refVal:{"ClassName":"[Ljava.lang.String;","ScFlag":0,"SerialVersionUID":12525169067719228231,"Fields":null,"RwDatas":null}
0x02: 标记号. 该值声明该对象支持序列化
0x00: 该类[[Ljava.lang.String;]所包含的域个数,有0个成员

第三部分是类[[Ljava.lang.String;]中各个属性的描述
0x78: TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕
[添加] [引用] [15] 类型:TC_ARRAY[0x75], refVal:{"ClassDesc":{"ClassName":"[Ljava.lang.String;","ScFlag":2,"SerialVersionUID":12525169067719228231,"Fields":[],"RwDatas":null},"SerialVer
sionUID":12525169067719228231,"Values":null,"JsonData":null}
0x70:   TC_NULL,标记后面的数据为空,对应java就是Null
0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x06: 该TC_STRING的长度[6]
0x313131313131: 字符串原文:111111
[添加] [引用] [16] 类型:TC_STRING[0x74], refVal:"111111"
0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x07: 该TC_STRING的长度[7]
0x33333333333333: 字符串原文:3333333
[添加] [引用] [17] 类型:TC_STRING[0x74], refVal:"3333333"
0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x0A: 该TC_STRING的长度[10]
0x34343434343434343434: 字符串原文:4444444444
[添加] [引用] [18] 类型:TC_STRING[0x74], refVal:"4444444444"

************************END[gifts2]************************
尝试获取第[0]个类(可序列化)[com.example.demo.model.UserEntity]-->第[2]个成员[id]值
************************BEGIN[id]************************
解析对象类型类成员[id]
[ReadTcObjFieldValue]解析类对象

0x73: TC_OBJECT. 声明这是一个新的对象(未被消费)
按顺序获取类描述,类数据块信息,获取第[0]块信息
第二部分是序列化的类的描述[深度:0]

0x72: TC_CLASSDESC. 声明这里开始一个新Class
0x0E: 类名字的长度[14]
0x6A6176612E6C616E672E4C6F6E67: 尝试读取类名[java.lang.Long]
0x3B8BE490CC8F23DF: SerialVersionUID,序列化ID,如果没有指定,则会由算法随机生成一个8byte的ID.
[添加] [引用] [19] 类型:TC_CLASSDESC[0x72], refVal:{"ClassName":"java.lang.Long","ScFlag":0,"SerialVersionUID":4290774380558885855,"Fields":null,"RwDatas":null}

0x02: 标记号. 该值声明该对象支持序列化
0x01: 该类[java.lang.Long]所包含的域个数,有1个成员

第三部分是类[java.lang.Long]中各个属性的描述
准备解析类[java.lang.Long]第1个属性

0x4A: 成员类型[J]
0x05: 成员名字长度
0x76616C7565: 成员名字[value]
类[java.lang.Long]第1个属性 :type: 0x4A, name: value, flag: 0x2, class:
0x78: TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕

按顺序获取类描述,类数据块信息,获取第[1]块信息
第四部分为对象的父类信息描述
第二部分是序列化的类的描述[深度:1]

0x72: TC_CLASSDESC. 声明这里开始一个新Class
0x10: 类名字的长度[16]
0x6A6176612E6C616E672E4E756D626572: 尝试读取类名[java.lang.Number]
0x86AC951D0B94E08B: SerialVersionUID,序列化ID,如果没有指定,则会由算法随机生成一个8byte的ID.
[添加] [引用] [20] 类型:TC_CLASSDESC[0x72], refVal:{"ClassName":"java.lang.Number","ScFlag":0,"SerialVersionUID":9704295249057472651,"Fields":null,"RwDatas":null}
0x02: 标记号. 该值声明该对象支持序列化
0x00: 该类[java.lang.Number]所包含的域个数,有0个成员
第三部分是类[java.lang.Number]中各个属性的描述
0x78: TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕

按顺序获取类描述,类数据块信息,获取第[2]块信息
0x70: TC_NULL,标记后面的数据为空,説明已经没有父类信息了[深度:2]
[添加] [引用] [21] 类型:TC_OBJECT[0x73], refVal:{"Classes":[{"ClassName":"java.lang.Long","ScFlag":2,"SerialVersionUID":4290774380558885855,"Fields":[{"FieldType":74,"FieldName":"value
","FieldOwnerScFlag":2,"FieldObjectClassName":"","FieldValue":null}],"RwDatas":null},{"ClassName":"java.lang.Number","ScFlag":2,"SerialVersionUID":9704295249057472651,"Fields":[],"RwDa
tas":null}],"SerialVersionUID":0,"JsonData":null,"RawData":null}

第五部分数据信息(类成员值),从父类的Field反序列化[java.lang.Long]
第五部分数据信息(类成员值),从父类的Field反序列化[java.lang.Number]->分解动作
第五部分数据信息(类成员值),从父类的Field反序列化[java.lang.Long]->分解动作
尝试获取第[0]个类(可序列化)[java.lang.Long]-->第[0]个成员[value]值
************************BEGIN[value]************************

0x01: 解析原生类型成员值 1
************************END[value]************************
************************END[id]************************
尝试获取第[0]个类(可序列化)[com.example.demo.model.UserEntity]-->第[3]个成员[others]值
************************BEGIN[others]************************
解析对象类型类成员[others]
[ReadTcObjFieldValue]解析类对象

0x73: TC_OBJECT. 声明这是一个新的对象(未被消费)
按顺序获取类描述,类数据块信息,获取第[0]块信息
第二部分是序列化的类的描述[深度:0]

0x72: TC_CLASSDESC. 声明这里开始一个新Class
0x11: 类名字的长度[17]
0x6A6176612E7574696C2E486173684D6170: 尝试读取类名[java.util.HashMap]
0x507DAC1C31660D1: SerialVersionUID,序列化ID,如果没有指定,则会由算法随机生成一个8byte的ID.
[添加] [引用] [22] 类型:TC_CLASSDESC[0x72], refVal:{"ClassName":"java.util.HashMap","ScFlag":0,"SerialVersionUID":362498820763181265,"Fields":null,"RwDatas":null}
0x03: 标记号. 拥有自己的writeObject, readObject, for example: HashMap, 此种类型需要每一个定义一个相应的结构体
0x02: 该类[java.util.HashMap]所包含的域个数,有2个成员

第三部分是类[java.util.HashMap]中各个属性的描述
准备解析类[java.util.HashMap]第1个属性
0x46: 成员类型[F]

0x0A: 成员名字长度
0x6C6F6164466163746F72: 成员名字[loadFactor]
类[java.util.HashMap]第1个属性 :type: 0x46, name: loadFactor, flag: 0x3, class:

准备解析类[java.util.HashMap]第2个属性
0x49: 成员类型[I]
0x09: 成员名字长度
0x7468726573686F6C64: 成员名字[threshold]
类[java.util.HashMap]第2个属性 :type: 0x49, name: threshold, flag: 0x3, class:
0x78: TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕

按顺序获取类描述,类数据块信息,获取第[1]块信息
0x70: TC_NULL,标记后面的数据为空,説明已经没有父类信息了[深度:1]
[添加] [引用] [23] 类型:TC_OBJECT[0x73], refVal:{"Classes":[{"ClassName":"java.util.HashMap","ScFlag":3,"SerialVersionUID":362498820763181265,"Fields":[{"FieldType":70,"FieldName":"loa
dFactor","FieldOwnerScFlag":3,"FieldObjectClassName":"","FieldValue":null},{"FieldType":73,"FieldName":"threshold","FieldOwnerScFlag":3,"FieldObjectClassName":"","FieldValue":null}],"R
wDatas":null}],"SerialVersionUID":0,"JsonData":null,"RawData":null}

第五部分数据信息(类成员值),从父类的Field反序列化[java.util.HashMap]
第五部分数据信息(类成员值),从父类的Field反序列化[java.util.HashMap]->分解动作
尝试获取第[0]个类(自定义序列化)[java.util.HashMap]
************************BEGIN************************
[JavaHashMap] has 0.000000 buckest
[JavaHashMap] has 0 mappings(size)

0x74: TC_STRING.代表一个new String.用String来引用对象(ReadNextEle)
[添加] [引用] [24] 类型:TC_STRING[0x74], refVal:"1qqqq"
0x71: TC_REFERENCE
0x7E0018: TC_REFERENCE引用序号[24]
0x74: TC_STRING.代表一个new String.用String来引用对象(ReadNextEle)
[添加] [引用] [25] 类型:TC_STRING[0x74], refVal:"4rrrr"
0x71: TC_REFERENCE
0x7E0019: TC_REFERENCE引用序号[25]
0x74: TC_STRING.代表一个new String.用String来引用对象(ReadNextEle)
[添加] [引用] [26] 类型:TC_STRING[0x74], refVal:"2wwww"
0x71: TC_REFERENCE
0x7E001A: TC_REFERENCE引用序号[26]
0x74: TC_STRING.代表一个new String.用String来引用对象(ReadNextEle)
[添加] [引用] [27] 类型:TC_STRING[0x74], refVal:"3eeee"
0x71: TC_REFERENCE
0x7E001B: TC_REFERENCE引用序号[27]
0x78:   TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕

************************END************************
************************END[others]************************
尝试获取第[0]个类(可序列化)[com.example.demo.model.UserEntity]-->第[4]个成员[others2]值
************************BEGIN[others2]************************
解析对象类型类成员[others2]
[ReadTcObjFieldValue]解析类对象

0x73: TC_OBJECT. 声明这是一个新的对象(未被消费)
按顺序获取类描述,类数据块信息,获取第[0]块信息
0x71:   TC_REFERENCE 标识引用
0x7E0016:       TC_REFERENCE引用序号[22](OBJECT-->TC_CLASSDESC)--> java.util.HashMap
[添加] [引用] [28] 类型:TC_OBJECT[0x73], refVal:{"Classes":[{"ClassName":"java.util.HashMap","ScFlag":3,"SerialVersionUID":362498820763181265,"Fields":[{"FieldType":70,"FieldName":"loa
dFactor","FieldOwnerScFlag":3,"FieldObjectClassName":"","FieldValue":null},{"FieldType":73,"FieldName":"threshold","FieldOwnerScFlag":3,"FieldObjectClassName":"","FieldValue":null}],"R
wDatas":[{"ClassDesc":null,"LoadFactor":0.75,"Thredshold":12,"Buckets":16,"Entries":{"1qqqq":"1qqqq","2wwww":"2wwww","3eeee":"3eeee","4rrrr":"4rrrr"}}]}],"SerialVersionUID":0,"JsonData
":null,"RawData":null}

第五部分数据信息(类成员值),从父类的Field反序列化[java.util.HashMap]
第五部分数据信息(类成员值),从父类的Field反序列化[java.util.HashMap]->分解动作
尝试获取第[0]个类(自定义序列化)[java.util.HashMap]
************************BEGIN************************
[JavaHashMap] has 0.000000 buckest
[JavaHashMap] has 0 mappings(size)

0x74: TC_STRING.代表一个new String.用String来引用对象(ReadNextEle)
[添加] [引用] [29] 类型:TC_STRING[0x74], refVal:"1tttt"
0x71: TC_REFERENCE
0x7E001D: TC_REFERENCE引用序号[29]
0x78:   TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕

************************END************************
************************END[others2]************************
尝试获取第[0]个类(可序列化)[com.example.demo.model.UserEntity]-->第[5]个成员[son]值
************************BEGIN[son]************************
解析对象类型类成员[son]
[ReadTcObjFieldValue]解析类对象
0x73: TC_OBJECT. 声明这是一个新的对象(未被消费)
按顺序获取类描述,类数据块信息,获取第[0]块信息
第二部分是序列化的类的描述[深度:0]

0x72: TC_CLASSDESC. 声明这里开始一个新Class
0x20: 类名字的长度[32]
0x636F6D2E6578616D706C652E64656D6F2E6D6F64656C2E536F6E456E74697479: 尝试读取类名[com.example.demo.model.SonEntity]
0x01: SerialVersionUID,序列化ID,如果没有指定,则会由算法随机生成一个8byte的ID.
[添加] [引用] [30] 类型:TC_CLASSDESC[0x72], refVal:{"ClassName":"com.example.demo.model.SonEntity","ScFlag":0,"SerialVersionUID":1,"Fields":null,"RwDatas":null}
0x02: 标记号. 该值声明该对象支持序列化
0x01: 该类[com.example.demo.model.SonEntity]所包含的域个数,有1个成员

第三部分是类[com.example.demo.model.SonEntity]中各个属性的描述
准备解析类[com.example.demo.model.SonEntity]第1个属性

0x4C: 成员类型[L]
0x07: 成员名字长度
0x536F6E4E616D65: 成员名字[SonName]
0x71: TC_REFERENCE 标识引用
0x7E0006: TC_REFERENCE引用序号[6]
类[com.example.demo.model.SonEntity]第1个属性 :type: 0x4C, name: SonName, flag: 0x2, class: Ljava/lang/String;
0x78: TC_ENDBLOCKDATA,在readObject中,表明数据已经读取完毕

按顺序获取类描述,类数据块信息,获取第[1]块信息
0x70: TC_NULL,标记后面的数据为空,説明已经没有父类信息了[深度:1]
[添加] [引用] [31] 类型:TC_OBJECT[0x73], refVal:{"Classes":[{"ClassName":"com.example.demo.model.SonEntity","ScFlag":2,"SerialVersionUID":1,"Fields":[{"FieldType":76,"FieldName":"SonNa
me","FieldOwnerScFlag":2,"FieldObjectClassName":"Ljava/lang/String;","FieldValue":null}],"RwDatas":null}],"SerialVersionUID":0,"JsonData":null,"RawData":null}

第五部分数据信息(类成员值),从父类的Field反序列化[com.example.demo.model.SonEntity]
第五部分数据信息(类成员值),从父类的Field反序列化[com.example.demo.model.SonEntity]->分解动作
尝试获取第[0]个类(可序列化)[com.example.demo.model.SonEntity]-->第[0]个成员[SonName]值
************************BEGIN[SonName]************************
解析对象类型类成员[SonName]

0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x13: 该TC_STRING的长度[19]
0x5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A: 字符串原文:ZZZZZZZZZZZZZZZZZZZ
[添加] [引用] [32] 类型:TC_STRING[0x74], refVal:"ZZZZZZZZZZZZZZZZZZZ"

************************END[SonName]************************
************************END[son]************************
尝试获取第[0]个类(可序列化)[com.example.demo.model.UserEntity]-->第[6]个成员[userName]值
************************BEGIN[userName]************************
解析对象类型类成员[userName]

0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x07: 该TC_STRING的长度[7]
0x31313131313131: 字符串原文:1111111
[添加] [引用] [33] 类型:TC_STRING[0x74], refVal:"1111111"

************************END[userName]************************
尝试获取第[0]个类(可序列化)[com.example.demo.model.UserEntity]-->第[7]个成员[userSex]值
************************BEGIN[userSex]************************
解析对象类型类成员[userSex]

0x74: TC_STRING.如果成员类型是对象,则后面跟着一个该对象的类名
0x0E: 该TC_STRING的长度[14]
0x3232323232323232326461736464: 字符串原文:222222222dasdd
[添加] [引用] [34] 类型:TC_STRING[0x74], refVal:"222222222dasdd"

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Protobuf(Protocol Buffers)是一种用于序列化结构化数据的语言无关、平台无关、可扩展的机制。它使用.proto文件定义数据结构和消息格式,并生成相应的代码用于序列化反序列化序列化原理: 1. 定义.proto文件,其中包含消息类型和字段定义。 2. 使用Protocol Buffers编译器将.proto文件编译成相应语言的代码。 3. 在代码中使用生成的类来设置消息的字段值。 4. 调用序列化方法将消息转换为字节流。 反序列化原理: 1. 接收字节流数据。 2. 调用反序列化方法解析字节流,并转换为特定语言的对象。 3. 使用对象中的字段值进行后续操作。 以下是使用Golang实现Protobuf的序列化反序列化的示例代码: ```go package main import ( "fmt" "log" "github.com/golang/protobuf/proto" ) // 定义.proto文件中的消息类型 type Person struct { Name string Age int32 Email string } func main() { // 创建Person对象 person := &Person{ Name: "Alice", Age: 25, Email: "alice@example.com", } // 序列化 data, err := proto.Marshal(person) if err != nil { log.Fatal("marshal error: ", err) } fmt.Printf("Serialized data: %v\n", data) // 反序列化 newPerson := &Person{} err = proto.Unmarshal(data, newPerson) if err != nil { log.Fatal("unmarshal error: ", err) } fmt.Printf("Deserialized data: %v\n", newPerson) } ``` 上述代码中,首先定义了一个`Person`消息类型,然后使用`proto.Marshal`方法将`person`对象序列化为字节流。接着使用`proto.Unmarshal`方法将字节流反序列化为`newPerson`对象。最后输出序列化前后的对象内容。 在使用该示例代码之前,需要通过`go get github.com/golang/protobuf/proto`命令安装Golang的Protobuf库。 希望以上信息能够对你有所帮助!如有更多问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值