java 序列化字节流解析

定义下面一个类然后执行序列化得到字节流写入文件,解析文件,基于这个过程了解java序列化的原理。

package com.heetian.erange.studio.crypt;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class TestSerialization {
    public static void main(String[] args) throws FileNotFoundException, IOException {
        child c = new child(new favorate("football"), 10, "parent");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e:\\result.obj")); 

        oos.writeObject(c);
        oos.close();
    }
}

class favorate implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    String name;
    // int age;
    public favorate() {

    }

    public favorate(String name) {
        this.name = name;
    }
}

class parent implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    String parentName;

    public parent() {

    }

    public parent(String name) {
        this.parentName = name;
    }
}

class child extends parent {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    int childAttr;
    favorate favo;

    public child(favorate favo, int childAttr, String name) {
        super(name);
        this.favo = favo;
        this.childAttr = childAttr;
    }
}

字节流解析过程

java序列化字节流16进制编码解析(下面4个字节是生成ObjectOutputStream时默认设置的)
AC ED:STREAM_MAGIC(占两个字节)
00 05:协议版本号(占两个字节)

73:TC_OBJECT(对象类描述开始,占1个字节)
先开始本类描述
72:TC_CLASSDESC(类描述开始,占1个字节)
00 25:Class名称长度(占2个字节,如00 25即表示类名长度为16*2+5个字符)
63 6f 6d 2e 68 65 65 74 69 61 6e 2e 65 72 61 6e 67 65 2e 73 74 75 64 69 6f 2e 63 72 79 70 74 2e 63 68 69 6c 64: com.heetian.erange.studio.crypt.child(37个字符)
00 00 00 00 00 00 00 01:序列化id占8个字节
02:是否可序列化标志占1个字节
00 02:域的个数占用2个字节
第1个域
49:域类型占1个字节(49代表i,即int类型)
00 09:域名长度占2个字节
63 68 69 6c 64 41 74 74 72:childAttr

第2个域
4c:域类型(4c代表L,即引用类型)
00 04:域名长度
66 61 76 6f :favo
引用说明
74:TC_STRING(用String来表示引用)
00 2a:String长度(2*16+10个字符)
4c 63 6f 6d 2f 68 65 65 74 69 61 6e 2f 65 72 61 6e 67 65 2f 73 74 75 64 69 6f 2f 63 72 79 70 74 2f 66 61 76 6f 72 61 74 65 3b Lcom/heetian/erange/studio/crypt/favorate;(42个字符)

78:TC_ENDBLOCKDATA(对象数据块结束标志)

再开始父类描述
72:TC_CLASSDESC(类描述开始,占1个字节)
00 26:Class名称长度(占两个字节,如00 26即表示类名长度为16*2+6个字符)
63 6f 6d 2e 68 65 65 74 69 61 6e 2e 65 72 61 6e 67 65 2e 73 74 75 64 69 6f 2e 63 72 79 70 74 2e 70 61 72 65 6e 74:com.heetian.erange.studio.crypt.parent(38个字符)
00 00 00 00 00 00 00 01:序列化id占8个字节
02:是否可序列化标志占1个字节
00 01:域个数占2个字节
4c:域类型(4c代表L,即引用类型)
00 0a:域名长度
70 61 72 65 6e 74 4e 61 6d 65:parentName 
74:TC_STRING(用String来表示引用名称)
00 12: String长度
4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b: Ljava/lang/String; 

78: TC_ENDBLOCKDATA(对象数据块结束标志)

70: TC_NULL(没有超类的标志)

第1个值String类型(从父类开始)
74:TC_STRING
00 06:String长度
70 61 72 65 6e 74:parent

第2个值int类型
00 00 00 0a:103个值fava对象类型
73:TC_OBJECT(对象描述开始)
72:TC_CLASSDESC(类描述开始)
00 28:Class类名长度
63 6f 6d 2e 68 65 65 74 69 61 6e 2e 65 72 61 6e 67 65 2e 73 74 75 64 69 6f 2e 63 72 79 70 74 2e 66 61 76 6f 72 61 74 65:com.heetian.erange.studio.crypt.favorate
00 00 00 00 00 01:序列化id占8个字节
02:是否序列化标志占1个字节
00 01:域个数
(引用类型)
{
4c:域类型(4c代表L,即引用类型)
00 04:域名长度
6e 61 6d 65:name

(String类型,5个字节指向一个已有String的引用地址,这里比较特殊,若这个name是一个其他类型,则会完整的描述这个类,这里考虑的是节省空间)
71 00 7e 00 0378:TC_ENDBLOCKDATA(对象块结束)
70:TC_NULL(没有父类标志)
第1个值描述
74:TC_STRING
00 08:String长度
66 6f 6f 74 62 61 6c 6c:football
}
(值类型)
{
49:域类型(49代表i,即int00 03: 域名长度
61 67 65:age
78:TC_ENDBLOCKDATA(对象块结束)
70:TC_NULL(没有父类标志)
第1个值int类型
00 00 00 0c:12
}

你可能感兴趣的:(Java)