成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Hessian 序列化、反序列化

原創 精選
運維
序列化參數有枚舉屬性,序列化端增加一個枚舉,能否正常反序列化?序列化子類,它和父類有同名參數,反序列化時,同名參數能否能正常賦值?

背景

問題和思考:

  • 序列化參數有枚舉屬性,序列化端增加一個枚舉,能否正常反序列化?
  • 序列化子類,它和父類有同名參數,反序列化時,同名參數能否能正常賦值?
  • 序列化對象增加參數,反序列化類不增加參數,能否正常反序列化?
  • 用于序列化傳輸的屬性,用包裝器比較好,還是基本類型比較好?

為什么要使用序列化和反序列化

  1. 程序在運行過程中,產生的數據,不能一直保存在內存中,需要暫時或永久存儲到介質(如磁盤、數據庫、文件)里進行保存,也可能通過網絡發送給協作者。程序獲取原數據,需要從介質,或網絡傳輸獲得。傳輸的過程中,只能使用二進制流進行傳輸。
  2. 簡單的場景,基本類型數據傳輸。通過雙方約定好參數類型,數據接收方按照既定規則對二進制流進行反序列化。

圖片

  1. 復雜的場景,傳輸數據的參數類型可能包括:基本類型、包裝器類型、自定義類、枚舉、時間類型、字符串、容器等。很難簡單通過約定來反序列化二進制流。需要一個通用的協議,共雙方使用,進行序列化和反序列化。

三種序列化協議及對比

序列化協議

特點

jdk
(jdk 自帶)

1. 序列化:除了 static、transient類型
2. 特點:強類型,安全性高,序列化結果攜帶類型信息
3. 反序列化:基于 Field 機制
4. 應用場景:深拷貝

fastjson
(第三方實現)

1. 可讀性好,空間占用小
2. 特點:弱類型,序列化結果不攜帶類型信息,可讀性強。有一些安全性問題
3. 反序列化:基于 Field 機制,兼容 Bean 機制
4. 應用場景:消息、透傳對象

hessian
(第三方實現)

1. 序列化:除了 static、transient 類型
2. 特點:強類型,體積小,可跨語言,序列化結果攜帶類型信息
3. 反序列化:基于 Field 機制,兼容 Bean 機制
4. 應用場景:RPC

對比

Father father = new Father();
father.name = "廚師";
father.comment = "川菜館";
father.simpleInt = 1;
father.boxInt = new Integer(10);
father.simpleDouble = 1;
father.boxDouble = new Double(10);
father.bigDecimal = new BigDecimal(11.5);

運行結果:

jdk序列化結果長度:626,耗時:55
jdk反序列化結果:Father{version=0, name='廚師', comment='川菜館', boxInt=10, simpleInt=1, boxDouble=10.0, simpleDouble=1.0, bigDecimal=11.5}耗時:87

hessian序列化結果長度:182,耗時:56
hessian反序列化結果:Father{version=0, name='廚師', comment='川菜館', boxInt=10, simpleInt=1, boxDouble=10.0, simpleDouble=1.0, bigDecimal=11.5}耗時:7

Fastjson序列化結果長度:119,耗時:225
Fastjson反序列化結果:Father{version=0, name='廚師', comment='川菜館', boxInt=10, simpleInt=1, boxDouble=10.0, simpleDouble=1.0, bigDecimal=11.5}耗時:69

分析:

  • jdk 序列化耗時最短,但是序列化結果長度最長,是其它兩種的 3 ~ 5 倍。
  • fastjson 序列化結果長度最短,但是耗時是其它兩種的 4 倍左右。
  • hessian 序列化耗時與 jdk 差別不大,遠小于 fastjson 序列化耗時。且與 jdk 相比,序列化結果占用空間非常有優勢。另外,hessian 的反序列化速度最快,耗時是其它兩種的 1/10。
  • 綜上比較,hessian 在序列化和反序列化表現中,性能最優。

Hessian 序列化實戰

實驗準備

父類

public class Father implements Serializable {

/**
* 靜態類型不會被序列化
*/
private static final long serialVersionUID = 1L;

/**
* transient 不會被序列化
*/
transient int version = 0;

/**
* 名稱
*/
public String name;

/**
* 備注
*/
public String comment;

/**
* 包裝器類型1
*/
public Integer boxInt;

/**
* 基本類型1
*/
public int simpleInt;

/**
* 包裝器類型2
*/
public Double boxDouble;

/**
* 基本類型2
*/
public double simpleDouble;

/**
* BigDecimal
*/
public BigDecimal bigDecimal;

public Father() {
}

@Override
public String toString() {
return "Father{" +
"version=" + version +
", name='" + name + '\'' +
", comment='" + comment + '\'' +
", boxInt=" + boxInt +
", simpleInt=" + simpleInt +
", boxDouble=" + boxDouble +
", simpleDouble=" + simpleDouble +
", bigDecimal=" + bigDecimal +
'}';
}
}

子類

public class Son extends Father {

/**
* 名稱,與father同名屬性
*/
public String name;

/**
* 自定義類
*/
public Attributes attributes;

/**
* 枚舉
*/
public Color color;

public Son() {
}

}

屬性-自定義類

public class Attributes implements Serializable {

private static final long serialVersionUID = 1L;

public int value;

public String msg;

public Attributes() {
}

public Attributes(int value, String msg) {
this.value = value;
this.msg = msg;
}

}

枚舉

public enum Color {

RED(1, "red"),
YELLOW(2, "yellow")
;

public int value;

public String msg;

Color() {
}

Color(int value, String msg) {
this.value = value;
this.msg = msg;
}
}

使用到的對象及屬性設置

Son son = new Son();
son.name = "廚師"; // 父子類同名字段,只給子類屬性賦值
son.comment = "川菜館";
son.simpleInt = 1;
son.boxInt = new Integer(10);
son.simpleDouble = 1;
son.boxDouble = new Double(10);
son.bigDecimal = new BigDecimal(11.5);
son.color = Color.RED;
son.attributes = new Attributes(11, "hello");

運行結果分析

使用 Hessian 序列化,結果寫入文件,使用 vim 打開。使用 16 進制方式查看,查看命令:%!xxd

00000000: 4307 6474 6f2e 536f 6e9a 046e 616d 6504  C.dto.Son..name.
00000010: 6e61 6d65 0763 6f6d 6d65 6e74 0662 6f78 name.comment.box
00000020: 496e 7409 7369 6d70 6c65 496e 7409 626f Int.simpleInt.bo
00000030: 7844 6f75 626c 650c 7369 6d70 6c65 446f xDouble.simpleDo
00000040: 7562 6c65 0a61 7474 7269 6275 7465 7305 uble.attributes.
00000050: 636f 6c6f 720a 6269 6744 6563 696d 616c color.bigDecimal
00000060: 6002 e58e a8e5 b888 4e03 e5b7 9de8 8f9c `.......N.......
00000070: e9a6 869a 915d 0a5c 430e 6474 6f2e 4174 .....].\C.dto.At
00000080: 7472 6962 7574 6573 9205 7661 6c75 6503 tributes..value.
00000090: 6d73 6761 9b05 6865 6c6c 6f43 0964 746f msga..helloC.dto
000000a0: 2e43 6f6c 6f72 9104 6e61 6d65 6203 5245 .Color..nameb.RE
000000b0: 4443 146a 6176 612e 6d61 7468 2e42 6967 DC.java.math.Big
000000c0: 4465 6369 6d61 6c91 0576 616c 7565 6304 Decimal..valuec.
000000d0: 3131 2e35 0a 11.5.

對其中的十六進制數逐個分析,可以拆解為一下結構:參考 hessian 官方文檔,鏈接:http://hessian.caucho.com/doc/hessian-serialization.html

序列化原理

圖片

序列化規則:

  1. 被序列化的類必須實現了 Serializable 接口

圖片

  1. 靜態屬性和 transient 變量,不會被序列化。

圖片

  1. 枚舉類型在序列化后,存儲的是枚舉變量的名字
  2. 序列化結果的結構:類定義開始標識 C -> 類名長度+類名 -> 屬性數量 -> (逐個)屬性名長度+屬性名 -> 開始實例化標識 -> (按照屬性名順序,逐個設置)屬性值(發現某個屬性是一個對象,循環這個過程)

圖片

反序列化

圖片

通俗原理圖:

圖片

圖片

解釋:這是前邊的序列化文件,可以對著這個結構理解反序列化的過程。

圖片

解釋:讀取到“C”之后,它就知道接下來是一個類的定義,接著就開始讀取類名,屬性個數和每個屬性的名稱。并把這個類的定義緩存到一個_classDefs 的 list 里。

圖片

解釋:通過讀取序列化文件,獲得類名后,會加載這個類,并生成這個類的反序列化器。這里會生成一個_fieldMap,key 為反序列化端這個類所有屬性的名稱,value 為屬性對應的反序列化器。

圖片

解釋:讀到 6 打頭的 2 位十六進制數時,開始類的實例化和賦值。

遺留問題解答:

  • 增加枚舉類型,反序列化不能正常讀取。

圖片

  • 原因:枚舉類型序列化結果中,枚舉屬性對應的值是枚舉名。反序列化時,通過枚舉類類名+枚舉名反射生成枚舉對象。枚舉名找不到就會報錯。
  • 反序列化為子類型,同名屬性值無法正常賦值。

圖片

圖片

圖片

  • 序列化對象增加參數,反序列化可以正常運行。

圖片

原因:反序列化時,是先通過類名加載同名類,并生成同名類的反序列化器,同名類每個屬性對應的反序列化器存儲在一個 map 中。在反序列化二進制文件時,通過讀取到的屬性名,到 map 中獲取對應的反序列化器。若獲取不到,默認是 NullFieldDeserializer.DESER。待到讀值的時候,僅讀值,不作 set 操作

  • 序列化和反序列化雙方都使用對象類型時,更改屬性類型,若序列化方不傳輸數據,序列化結果是‘N’,能正常反序列化。但是對于一方是基本類型,更改屬性類型后,因為 hessian 對于基本類型使用不同范圍的值域,所以無法正常序列化。
責任編輯:未麗燕 來源: 字節跳動技術團隊
相關推薦

2011-06-01 15:05:02

序列化反序列化

2009-08-24 17:14:08

C#序列化

2009-08-06 11:16:25

C#序列化和反序列化

2011-05-18 15:20:13

XML

2023-12-13 13:49:52

Python序列化模塊

2018-03-19 10:20:23

Java序列化反序列化

2011-06-01 14:50:48

2019-11-20 10:07:23

web安全PHP序列化反序列化

2009-06-14 22:01:27

Java對象序列化反序列化

2009-08-25 14:24:36

C#序列化和反序列化

2021-11-18 07:39:41

Json 序列化Vue

2009-09-09 16:10:11

.NET序列化和反序列

2012-04-13 10:45:59

XML

2009-08-25 14:43:26

C#序列化和反序列化

2009-09-09 15:47:27

XML序列化和反序列化

2009-09-09 14:45:41

XML序列化和反序列化

2010-03-19 15:54:21

Java Socket

2009-07-29 13:39:02

JSON序列化和反序列ASP.NET AJA

2016-09-21 00:15:27

2016-01-05 15:10:59

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美精品在线看 | 日韩在线视频一区二区三区 | 欧美另类视频 | 色爱综合网 | 欧美在线视频一区二区 | 欧美美女二区 | 久久综合九色综合欧美狠狠 | 一区精品国产欧美在线 | 国产精品日产欧美久久久久 | xxx.在线观看 | 国产在线精品一区二区 | h片免费看 | 男人的天堂久久 | 综合久久久久 | 男女网站在线观看 | 在线看一区二区 | 国产精品久久久久久久久免费软件 | 午夜天堂精品久久久久 | 免费看欧美一级片 | 成人在线精品 | 久久精品国产免费一区二区三区 | 国产黄色精品 | 免费国产精品久久久久久 | 一区二区在线免费播放 | 草草视频在线观看 | 久草久草久草 | 黄网站在线播放 | 国产成人一区二 | 免费黄色av | 黄色一级大片在线免费看产 | 伦理午夜电影免费观看 | www.夜夜骑.com | 中文字幕成人在线 | 日韩在线免费 | 色欧美日韩 | 日韩1区 | 精品视频一区二区三区在线观看 | 欧美黄色片| 日韩欧美一区二区三区免费看 | 日韩欧美在线免费观看视频 | 久久综合伊人 |