程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java序列化機制與道理的深刻剖析

Java序列化機制與道理的深刻剖析

編輯:關於JAVA

Java序列化機制與道理的深刻剖析。本站提示廣大學習愛好者:(Java序列化機制與道理的深刻剖析)文章只能為提供參考,不一定能成為您想要的結果。以下是Java序列化機制與道理的深刻剖析正文


Java序列化算法透析

    Serialization(序列化)是一種將對象以連續串的字節描寫的進程;反序列化deserialization是一種將這些字節重建成一個對象的進程。Java序列化API供給一種處置對象序列化的尺度機制。在這裡你能學到若何序列化一個對象,甚麼時刻須要序列化和Java序列化的算法,我們用一個實例來示范序列化今後的字節是若何描寫一個對象的信息的。
序列化的需要性

    Java中,一切都是對象,在散布式情況中常常須要將Object從這一端收集或裝備傳遞到另外一端。這就須要有一種可以在兩頭傳輸數據的協定。Java序列化機制就是為懂得決這個成績而發生。
若何序列化一個對象

一個對象可以或許序列化的條件是完成Serializable接口,Serializable接口沒無方法,更像是個標志。有了這個標志的Class就可以被序列化機制處置。

import java.io.Serializable;      
class TestSerial implements Serializable {      
           public byte version = 100;    
           public byte count = 0;      
}

    然後我們寫個法式將對象序列化並輸入。ObjectOutputStream能把Object輸入成Byte流。我們將Byte流臨時存儲到temp.out文件裡。

public static void main(String args[]) throws IOException {      
    FileOutputStream fos = new FileOutputStream("temp.out");      
    ObjectOutputStream oos = new ObjectOutputStream(fos);      
    TestSerial ts = new TestSerial();      
    oos.writeObject(ts);      
    oos.flush();      
    oos.close();      
}

    假如要從耐久的文件中讀取Bytes重建對象,我們可使用ObjectInputStream。

public static void main(String args[]) throws      IOException {      
      FileInputStream fis = new FileInputStream("temp.out");      
      ObjectInputStream oin = new ObjectInputStream(fis);      
      TestSerial ts = (TestSerial) oin.readObject();      
       System.out.println("version="+ts.version);      
 }

履行成果為

100.
對象的序列化格局

將一個對象序列化後是甚麼模樣呢?翻開適才我們將對象序列化輸入的temp.out文件,以16進制方法顯示。內容應當以下:

AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 65

73 74 A0 0C 34 00 FE B1 DD F9 02 00 02 42 00 05

63 6F 75 6E 74 42 00 07 76 65 72 73 69 6F 6E 78

70 00 64

這一坨字節就是用來描寫序列化今後的TestSerial對象的,我們留意到TestSerial類中只要兩個域:

    public byte version = 100;

    public byte count = 0;

且都是byte型,實際上存儲這兩個域只須要2個byte,然則現實上temp.out占領空間為51bytes,也就是說除數據之外,還包含了對序列化對象的其他描寫。
Java的序列化算法

序列化算法普通會按步調做以下工作:

◆將對象實例相干的類元數據輸入。

◆遞歸地輸入類的超類描寫直到不再有超類。

◆類元數據完了今後,開端從最頂層的超類開端輸入對象實例的現實數據值。

◆從上至下遞歸輸入實例的數據

我們用另外一個更完全籠罩一切能夠湧現的情形的例子來講明:

    class parent implements Serializable {      
           int parentVersion = 10;      
    } 

    class contain implements Serializable{      
           int containVersion = 11;      
    } 

    public class SerialTest extends parent implements Serializable {      
           int version = 66;      
           contain con = new contain();                  
           public int getVersion() {      
                  return version;      
           }      
           public static void main(String args[]) throws IOException {      
                  FileOutputStream fos = new FileOutputStream("temp.out");      
                  ObjectOutputStream oos = new ObjectOutputStream(fos);      
                  SerialTest st = new SerialTest();      
                  oos.writeObject(st);      
                  oos.flush();      
                  oos.close();      
           }      
    }

這個例子是相當的直白啦。SerialTest類完成了Parent超類,外部還持有一個Container對象。

序列化後的格局以下:

AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 65

73 74 05 52 81 5A AC 66 02 F6 02 00 02 49 00 07

76 65 72 73 69 6F 6E 4C 00 03 63 6F 6E 74 00 09

4C 63 6F 6E 74 61 69 6E 3B 78 72 00 06 70 61 72

65 6E 74 0E DB D2 BD 85 EE 63 7A 02 00 01 49 00

0D 70 61 72 65 6E 74 56 65 72 73 69 6F 6E 78 70

00 00 00 0A 00 00 00 42 73 72 00 07 63 6F 6E 74

61 69 6E FC BB E6 0E FB CB 60 C7 02 00 01 49 00

0E 63 6F 6E 74 61 69 6E 56 65 72 73 69 6F 6E 78

70 00 00 00 0B

我們來細心看看這些字節都代表了啥。開首部門,見色彩:

  1. AC ED: STREAM_MAGIC. 聲明應用了序列化協定.
  2. 00 05: STREAM_VERSION. 序列化協定版本.
  3. 0x73: TC_OBJECT. 聲明這是一個新的對象.  

序列化算法的第一步就是輸入對象相干類的描寫。例子所示對象為SerialTest類實例,是以接上去輸入SerialTest類的描寫。見色彩:

  1. 0x72: TC_CLASSDESC. 聲明這裡開端一個新Class。
  2. 00 0A: Class名字的長度.
  3. 53 65 72 69 61 6c 54 65 73 74: SerialTest,Class類名.
  4. 05 52 81 5A AC 66 02 F6: SerialVersionUID, 序列化ID,假如沒有指定,則會由算法隨機生成一個8byte的ID.
  5. 0x02: 標志號. 該值聲明該對象支撐序列化。
  6. 00 02: 該類所包括的域個數。

接上去,算法輸入個中的一個域,int version=66;見色彩:

  1. 0x49: 域類型. 49 代表"I", 也就是Int.
  2. 00 07: 域名字的長度.
  3. 76 65 72 73 69 6F 6E: version,域名字描寫.

然後,算法輸入下一個域,contain con = new contain();這個有點特別,是個對象。描寫對象類型援用時須要應用JVM的尺度對象簽名表現法,見色彩:

  1. 0x4C: 域的類型.
  2. 00 03: 域名字長度.
  3. 63 6F 6E: 域名字描寫,con
  4. 0x74: TC_STRING. 代表一個new String.用String來援用對象。
  5. 00 09: 該String長度.
  6. 4C 63 6F 6E 74 61 69 6E 3B: Lcontain;, JVM的尺度對象簽名表現法.
  7. 0x78: TC_ENDBLOCKDATA,對象數據塊停止的標記

.接上去算法就會輸入超類也就是Parent類描寫了,見色彩:

  1. 0x72: TC_CLASSDESC. 聲明這個是個新類.
  2. 00 06: 類名長度.
  3. 70 61 72 65 6E 74: parent,類名描寫。
  4. 0E DB D2 BD 85 EE 63 7A: SerialVersionUID, 序列化ID.
  5. 0x02: 標志號. 該值聲明該對象支撐序列化.
  6. 00 01: 類中域的個數.

下一步,輸入parent類的域描寫,int parentVersion=100;同見色彩:

  1. 0x49: 域類型. 49 代表"I", 也就是Int.
  2. 00 0D: 域名字長度.
  3. 70 61 72 65 6E 74 56 65 72 73 69 6F 6E: parentVersion,域名字描寫。
  4. 0x78: TC_ENDBLOCKDATA,對象塊停止的標記。
  5. 0x70: TC_NULL, 解釋沒有其他超類的標記。.

到此為止,算法曾經對一切的類的描寫都做了輸入。下一步就是把實例對象的現實值輸入了。這時候候是從parent Class的域開端的,見色彩:

  1. 00 00 00 0A: 10, parentVersion域的值.

還有SerialTest類的域:

  1. 00 00 00 42: 66, version域的值.

再往後的bytes比擬成心思,算法須要描寫contain類的信息,要記住,如今還沒有對contain類停止過描寫,見色彩:

  1. 0x73: TC_OBJECT, 聲明這是一個新的對象.
  2. 0x72: TC_CLASSDESC聲明這裡開端一個新Class.
  3. 00 07: 類名的長度.
  4. 63 6F 6E 74 61 69 6E: contain,類名描寫.
  5. FC BB E6 0E FB CB 60 C7: SerialVersionUID, 序列化ID.
  6. 0x02: Various flags. 標志號. 該值聲明該對象支撐序列化
  7. 00 01: 類內的域個數。

.輸入contain的獨一的域描寫,int containVersion=11;

  1. 0x49: 域類型. 49 代表"I", 也就是Int..
  2. 00 0E: 域名字長度.
  3. 63 6F 6E 74 61 69 6E 56 65 72 73 69 6F 6E: containVersion, 域名字描寫.
  4. 0x78: TC_ENDBLOCKDATA對象塊停止的標記.

這時候,序列化算法會檢討contain能否有超類,假如有的話會接著輸入。

  1. 0x70:TC_NULL,沒有超類了。

最初,將contain類現實域值輸入。

  1. 00 00 00 0B: 11, containVersion的值.

OK,我們評論辯論了java序列化的機制和道理,願望能對同窗們有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved