FST序列化/反序列化

FST序列化/反序列化一、FST序列化存储格式基本上所有以Byte形式存储的序列化对象都是类似的存储结构,不管class文件、so文件、dex文件都是类似,可以看看这个,这方面没有什么创新的格式,最多是在字段内容上做了一些压缩优化,包括我们最常使用的utf-8编码都是这个做法。FST的序列化存储和一般的字节格式化存储方案也没有标新立异的地方,比如下面这个FTS的序列化字节文件0000000...
摘要由CSDN通过智能技术生成

FST序列化/反序列化

一、FST序列化存储格式

基本上所有以Byte形式存储的序列化对象都是类似的存储结构,不管class文件、so文件、dex文件都是类似,可以看看这个,这方面没有什么创新的格式,最多是在字段内容上做了一些压缩优化,包括我们最常使用的utf-8编码都是这个做法。

FST的序列化存储和一般的字节格式化存储方案也没有标新立异的地方,比如下面这个FTS的序列化字节文件

00000001:  0001 0f63 6f6d 2e66 7374 2e46 5354 4265
00000010:  616e f701 fc05 7630 7374 7200 

格式:Header|类名长度|类名String|字段1类型(1Byte) | [长度] | 内容|字段2类型(1Byte) | [长度] | 内容|…

0000:字节数组类型:00标识OBJECT
0001:类名编码,00标识UTF编码,01表示ASCII编码
0002:Length of class name (1Byte) = 15
0003~0011:Class name string (15Byte)
0012:Integer类型标识 0xf7
0013:Integer的值=1
0014:String类型标识 0xfc
0015:String的长度=5
0016~001a:String的值"v0str"
001b~001c:END

从上面可以看到Integer类型序列化后只占用了一个字节(值等于1),并不像在内存中占用4Byte,所以可以看出是根据一定规则做了压缩,具体代码看FSTObjectInput#instantiateSpecialTag中对不同类型的读取,FSTObjectInput也定义不同类型对应的枚举值:

public class FSTObjectOutput implements ObjectOutput {
   

    private static final FSTLogger LOGGER = FSTLogger.getLogger(FSTObjectOutput.class);
    public static Object NULL_PLACEHOLDER = new Object() {
    public String toString() {
    return "NULL_PLACEHOLDER"; }};
    public static final byte SPECIAL_COMPATIBILITY_OBJECT_TAG = -19; // see issue 52
    public static final byte ONE_OF = -18;
    public static final byte BIG_BOOLEAN_FALSE = -17;
    public static final byte BIG_BOOLEAN_TRUE = -16;
    public static final byte BIG_LONG = -10;
    public static final byte BIG_INT = -9;
    public static final byte DIRECT_ARRAY_OBJECT = -8;
    public static final byte HANDLE = -7;
    public static final byte ENUM = -6;
    public static final byte ARRAY = -5;
    public static final byte STRING = -4;
    public static final byte TYPED = -3; // var class == object written class
    public static final byte DIRECT_OBJECT = -2;
    public static final byte NULL = -1;
    public static final byte OBJECT = 0;
    protected FSTEncoder codec;
    ...
}

FST序列化和反序列化原理

对Object进行Byte序列化,相当于做了持久化的存储,在反序列的时候,如果Bean的定义发生了改变,那么反序列化器就要做兼容的解决方案,我们知道对于JDK的序列化和反序列,serialVersionUID对版本控制起了很重要的作用。FTS对这个问题的解决方案是通过@Version注解进行排序。

在进行反序列操作的时候,FST会先反射或者对象Class的所有成员,并对这些成员进行了排序,请注意这里被标红的排序,因为这个排序对兼容起了关键作用,也就是@Version的原理。在FSTClazzInfo中定义了一个defFieldComparator比较器,用于对Bean的所有Field进行排序:

public final class FSTClazzInfo {
   
    public static final Comparator<FSTFieldInfo> defFieldComparator = new Comparator<FSTFieldInfo>() {
   
        @Override
        public int compare(FSTFieldInfo o1, FSTFieldInfo o2) {
   
            int res = 0;

            if ( o1.getVersion() != o2.getVersion() ) {
   
                return o1.getVersion() < o2.getVersion() ? -1 : 1;
            }

            // order: version, boolean, primitives, conditionals, object references
            if (o1.getType() == boolean.class && o2.getType() != boolean.class) {
   
                return -1;
            }
            if (o1.getType() != boolean.class && o2.getType() == boolean.class) {
   
                return 1;
            }

            if (o1.isConditional() && !o2.isConditional()) {
   
                res = 1;
            } else if (!o1.isConditional() && o2.isConditional()) {
   
                res = -1;
            } else if (o1.isPrimitive() && !o2.isPrimitive()) {
   
                res = -1;
            } else if (!o1.isPrimitive() && o2.isPrimitive())
                res = 1;
//                if (res == 0) // 64 bit / 32 bit issues
//                    res = (int) (o1.getMemOffset() - o2.getMemOffset());
            if (res == 0)
                res = o1.getType().getSimpleName().compareTo(o2.getType().getSimpleName());
            if (res == 0)
                res = o1.getName().
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值