为什么如此高效?解密kryo各个数据类型的序列化编码机制,强( 四 )


4 , 字节类型序列化实现类为:DefaultSerializers $ ByteSerializer , 序列化:直接将字节写入字节流中即可 。
5 , char类型序列化实现类为:DefaultSerializers $ CharSerializer
输出#writeChar
/** Writes a 2 byte char. Uses BIG_ENDIAN byte order. */ public void writeChar (char value) throws KryoException {require(2);buffer[position++] = (byte)(value >>> 8);buffer[position++] = (byte)value; }序列化:char在java中使用2字节存储(unicode) , kryo在序列化时 , 按大端字节的顺序 , 将char写入字节流
6 , 短类型序列化实现类为DefaultSerializers $ ShortSerializer Output#writeShort
/** Writes a 2 byte short. Uses BIG_ENDIAN byte order. */ public void writeShort (int value) throws KryoException {require(2);buffer[position++] = (byte)(value >>> 8);buffer[position++] = (byte)value; }序列化:与char类型序列化一样 , 采用大端字节顺序存储 。
7 , long类型序列化实现类为:DefaultSerializers $ LongSerializer
输出#writeLong
public int writeLong (long value, boolean optimizePositive) throws KryoException {return writeVarLong(value, optimizePositive);}序列化:采用变长字节(1-9)位来存储long , 其编码规则与int变长类型一致 , 每个字节的高位表示表示结束 , 1:表示还需要继续读取下一个字节 , 0:表示结束 。
8 , 浮点类型序列化实现类为:DefaultSerializers $ FloatSerializer
/** Writes a 4 byte float. */public void writeFloat (float value) throws KryoException { writeInt(Float.floatToIntBits(value));}/** Writes a 4 byte int. Uses BIG_ENDIAN byte order. */public void writeInt (int value) throws KryoException { require(4); byte[] buffer = this.buffer; buffer[position++] = (byte)(value >> 24); buffer[position++] = (byte)(value >> 16); buffer[position++] = (byte)(value >> 8); buffer[position++] = (byte)value;}序列化:首先将float按照IEEE 754编码标准 , 转换为int类型 , 然后按大端序列 , 使用固定长度4字节来存储float , 这里之所以不使用变长字节来存储float , 是因为使用Float .floatToIntBits(value)产生的值 , 比较大 , 基本都需要使用4个字才能存储 , 如果使用变长字节 , 则需要5个字节 , 反而消耗的存储空间大小 。
9 , DefaultSerializers $ DoubleSerializer输出#writeDouble序列化:首先将Double遵循IEEE 754编码标准转换为Long , 然后才去固定8字节存储 。 随即 , 介绍了8种基本类型(boolean , byte , char , short , int , float ,long , double)和String类型的序列化与反序列化 。
10 , BigInteger序列化实现类为:DefaultSerializers $ BigIntegerSerializer/** Writes an 8 byte double. */public void writeDouble (double value) throws KryoException { writeLong(Double.doubleToLongBits(value));}/** Writes an 8 byte long. Uses BIG_ENDIAN byte order. */public void writeLong (long value) throws KryoException { require(8); byte[] buffer = this.buffer; buffer[position++] = (byte)(value >>> 56); buffer[position++] = (byte)(value >>> 48); buffer[position++] = (byte)(value >>> 40); buffer[position++] = (byte)(value >>> 32); buffer[position++] = (byte)(value >>> 24); buffer[position++] = (byte)(value >>> 16); buffer[position++] = (byte)(value >>> 8); buffer[position++] = (byte)value;}BigInteger序列化实现 , 整体格式与String类型一样 , 由length +内容构成 。

  1. 如果为null , 则写入一个字节 , 其增量0 , 表示长度为0 。
  2. 如果为BigInteger.ZERO , 则长度写入2 , 随后再写入1个字节的内容 , 字节内容为0 , 表示ZERO 。
  3. 将BigInteger转换成byte []数组 , 首先写入长度=(byte长度+ 1) , 然后写入byte的内容即可 。
11 , BigDecimal序列化实现类为:DefaultSerializers $ BigDecimalSerializer
BigDecimal的序列化与BigInteger相同 , 首先是通过BigDecimal#unscaledValue方法返回对应的BigInteger , 然后序列化 , 在反序列化时通过BigInteger创建对应的BigDecimal即可 。
12 , 类实例序列化实现类为:DefaultSerializers $ ClassSerializer
public void write (Kryo kryo, Output output, Class object) { kryo.writeClass(output, object); // @1 output.writeByte((object != null// @2}代码@ 1:调用Kryo的writeClass方法序列化Class实例 。 代码@ 2:写入是否是包装类型(针对8种基本类型) 。
接下来我们重点分析Kryo#writeClass
public Registration writeClass (Output output, Class type) {if (output == null) throw new IllegalArgumentException("output cannot be null.");try {return classResolver.writeClass(output, type);// @1} finally {if (depth == 0// @2}}代码@ 2:完成一次写入后 , 需要重置Kryo中的临时数据结构 , 这也就是kryo实例非线程安全的原因 , 其中一些重要的数据结构会 。 代码@ 1:首先调用ClassResolver.wreteClass方法 。 再ClassResolver.writeClass中详细说明 。