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
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章