JDK序列化方案

JDK序列化方案

示例代码如下:

package com.zhuke.serial.jdk;

import com.zhuke.serial.jdk.entity.Apple;
import org.apache.commons.codec.binary.Hex;

import java.io.*;
import java.util.Arrays;

/**
 * Created by ZHUKE on 2017/1/20.
 */
public class Main {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Apple apple = new Apple();
        defaultWriteObject(apple);
        Apple object = (Apple) defaultReadObject("obj.serial");
        System.out.println(object);
        System.out.println("serial info: " + Hex.encodeHex(readSerialInfo("obj.serial")));
    }

    private static void defaultWriteObject(Object obj) throws IOException {
        FileOutputStream fos = new FileOutputStream("obj.serial");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
    }

    private static Object defaultReadObject(String path) throws IOException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream(path);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object read = ois.readObject();
        ois.close();
        return read;
    }

    private static byte[] readSerialInfo(String path) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(path);
        byte[] b = new byte[1024];
        int r = fileInputStream.read();
        int len = 0;
        for (len = 0; r != -1; len++) {
            b[len] = (byte) r;
            r = fileInputStream.read();
        }
        return Arrays.copyOfRange(b, 0, len);
    }
}

16进制表示序列化后的信息为:

aced000573720021636f6d2e7a68756b652e73657269616c2e6a646b2e656e746974792e4170706c655a97b46baef464d90200014c00046e616d657400124c6a6176612f6c616e672f537472696e673b78720021636f6d2e7a68756b652e73657269616c2e6a646b2e656e746974792e467275697410be85a9044b3d4e02000149000677656967687478700000000a74000d44656661756c74204170706c65

其中各部分内容表示如下:

  1. 0xac 0xed: STREAM_MAGIC流的幻数,用于标记序列化协议
  2. 0x00 0x05: STREAM_VERSION标记序列化协议的版本

以上两类信息在ObjectOutputStream类对象构造时就被写入到了序列化的缓冲区中

new ObjectOutputStream(obj)
    writeHeader()
        /**
         * Magic number that is written to the stream header.
         */
        final static short STREAM_MAGIC = (short)0xaced;

        /**
         * Version number that is written to the stream header.
         */
        final static short STREAM_VERSION = 5;
        bout.writeShort(STREAM_MAGIC);
        bout.writeShort(STREAM_VERSION);
  1. 0x73: TC_OBJECT. 声明这是一个新的对象
  2. 0x72: TC_CLASSDESC. 声明这是一个新的类描述
  3. 0x00 0x21: 类名长度,换算成十进制为33
  4. 636f6d2e7a68756b652e73657269616c2e6a646b2e656e746974792e4170706c65 表示类名称:com.zhuke.serial.jdk.entity.Apple
  5. 5a97b46baef464d9: 序列化ID,long型,占8位
  6. 0x02: 标记号,该字节的8位代表不同含义:
SC_EXTERNALIZABLE 0x04 : 该类实现了java.io.Externalizable接口 
SC_BLOCK_DATA 0x08 : Externalizable接口的writeExternal方法写入的数据
SC_SERIALIZABLE 0x02 : 该类实现了java.io.Serializable接口
SC_WRITE_METHOD 0x01 : 该序列化类实现了writeObject方法 
SC_ENUM 0x10 : 该类是枚举(enum)类型 
该标记号通过上述信息进行或运算(|)而获得
  1. 0x00 0x01: 代表类属性域的个数
  2. 0x4c: 域类型,0x4c代表L,即该域为java对象类型
  3. 0x00 0x04: 域名称长度
  4. 0x6e 0x61 0x6d 0x65: 域名称name
  5. 0x74: TC_STRING 一个新字符串
  6. 0x00 0x12: 域类型长度
  7. 4c6a6176612f6c616e672f537472696e673b :对象类型签名Ljava/lang/String;
  8. 0x78: TC_ENDBLOCKDATA 对象数据块结束标志
  1. 0x72: TC_CLASSDESC 声明这是一个新的类描述
  2. 0x00 0x21: 类名长度,换算成十进制为33
  3. 636f6d2e7a68756b652e73657269616c2e6a646b2e656e746974792e4672756974: 类名
  4. 0x02: 标记号
  5. 标记号
  6. 域个数
  7. 域类型
  8. 域名称长度
  9. 域名称weight
  10. 对象结束标志
  11. 0x70: TC_NULL再没有父类的标志

总结:
JDK序列化的基本步骤:
a) 输出序列化的头部信息,包括标识序列化协议的幻数以及协议的版本

b) 按照由子类到父类的顺序,递归的输出类的描述信息,直到不再有父类为止;类描述信息按照类元数据,类属性信息的顺序写入序列化流中

c) 按照由父类到子类的顺序,递归的输出对象域的实际数据值;而对象的属性信息是按照基本数据类型到java对象类型的顺序写入序列化流中;其中java对象类型的属性会从步骤a)重新开始递归的输出,直到不再存在java对象类型的属性。

但是这种序列化是不安全,因为序列化二进制格式完全编写在文档中或者在网络中传播,并且完全可逆。可以通过自定义序列化的方法,将序列化的值进行加密后,解决安全问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • JAVA序列化机制的深入研究 对象序列化的最主要的用处就是在传递,和保存对象(object)的时候,保证对象的完整...
    时待吾阅读 10,990评论 0 24
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,253评论 19 139
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 11,297评论 6 13
  • 最近在做文章转移,全部文字请点击http://fog-li.lofter.com/ ​文章来源 http://zh...
    Fog_li阅读 840评论 0 1
  • 同人不同命!我们每个人都有属于自己的故事,而身在自己故事中会当局者迷,常常不知道自己究竟想要什么样的生活,总会感叹...
    柳小欧阅读 412评论 0 1