下面我將從以下幾點(diǎn)來介紹:
1、什么是序列化和反序列化?
2、Java對象為什么要實(shí)現(xiàn)Serializable接口?
3、使用Serializable接口需要注意的問題?
4、常見的序列化技術(shù)?
5、序列化技術(shù)的選型
什么是序列化和反序列化?
序列化就是把對象的狀態(tài)信息轉(zhuǎn)化為可存儲或傳輸?shù)男问竭^程,也就是把對象轉(zhuǎn)化為字節(jié)序列的過程稱為對象的序列化。
序列化的逆向過程,把字節(jié)數(shù)組反序列化為對象,把字節(jié)序列恢復(fù)為對象的過程成為對象的反序列化。
Java對象為什么要實(shí)現(xiàn)Serializable接口?
(1)對象持久化:把對象的字節(jié)序列永久地保存到硬盤上,通常存放在一個(gè)文件中;
Java平臺允許我們在內(nèi)存中創(chuàng)建可復(fù)用的Java對象,但一般情況下,只有當(dāng)JVM處于運(yùn)行時(shí),這些對象才可能存在,即,這些對象的生命周期不會比JVM的生命周期更長。但是在現(xiàn)實(shí)應(yīng)用中,就可能要求在JVM停止運(yùn)行之后能夠保存(序列化)指定的對象,并在將來重新讀取被保存的對象。Java對象序列化就能夠幫助我們實(shí)現(xiàn)該功能。
(2)網(wǎng)絡(luò)傳輸對象:在網(wǎng)絡(luò)上傳送對象的字節(jié)序列。可以通過序列化把主機(jī)A進(jìn)程上的對象序列化為二進(jìn)制序列,傳輸?shù)街鳈C(jī)B上的進(jìn)程從序列中重構(gòu)出該對象。
還有一種情況是兩個(gè)進(jìn)程之間進(jìn)行通信時(shí),兩方發(fā)送各種類型的數(shù)據(jù)。無論何種類型的數(shù)據(jù),都會以二進(jìn)制序列的形式在網(wǎng)絡(luò)上進(jìn)行傳送。發(fā)送方需要把對象轉(zhuǎn)換成字節(jié)序列,才能在網(wǎng)絡(luò)上傳送;接收方則需要把字節(jié)序列再恢復(fù)成對象。
在java中只要一個(gè)類實(shí)現(xiàn)了java.io.Serializable接口,那么它就可以被序列化。
JDK提供了Java對象的序列化方式,主要通過輸出流 java.io.Serializable Java的序列化機(jī)制是通過判斷類的serialVersionUID來驗(yàn)證版本一致性的。在進(jìn)行反序列化時(shí),JVM會把傳來的字節(jié)流中的serialVersionUID與本地相應(yīng)實(shí)體類的serialVersionUID進(jìn)行比較,如果相同就認(rèn)為是一致的,可以進(jìn)行反序列化,否則就會出現(xiàn)序列化版本不一致的異常,即是InvalidCastException。 如果沒有為指定的class配置serialVersionUID,那么java編譯器會自動給這個(gè)class進(jìn)行一個(gè)摘要算法,類似于指紋算法,只要這個(gè)文件有任何改動,得到的UID就會截然不同的,可以保證在這么多類中,這個(gè)編號是唯一的 serialVersionUID有兩種生成方式 (1)默認(rèn)的1L,比如:privatestaticfinallongserialVersionUID=1L; (2)根據(jù)類名、接口名、成員方法及屬性等來生成一個(gè)64位的哈希字段 當(dāng)實(shí)現(xiàn)java.io.Serializable接口的類沒有顯式地定義一個(gè)serialVersionUID變量時(shí)候,Java序列化機(jī)制會根據(jù)編譯的Class自動生成一個(gè)serialVersionUID作序列化版本比較用,這種情況下,如果Class文件(類名,方法明等)沒有發(fā)生變化(增加空格,換行,增加注釋等等),就算再編譯多次,serialVersionUID也不會變化的。 序列化時(shí)并不保存靜態(tài)變量,這其實(shí)比較容易理解,序列化保存的是對象的狀態(tài),靜態(tài)變量屬于類的狀態(tài),因此序列化并不保存靜態(tài)變量。 作用是控制變量的序列化,在變量聲明前加上該關(guān)鍵字,可以阻止該變量被序列化到文件中,在被反序列化后,transient變量的值設(shè)為初始值,如int型的是0. (1)同一個(gè)對象兩次(開始寫入文件到最終關(guān)閉流的這個(gè)過程算一次),如果不關(guān)閉流寫入文件兩次,則第二次寫入對象時(shí)文件只增加5字節(jié)。 (2)Java序列化機(jī)制為了節(jié)省磁盤空間,具有特定的存儲規(guī)則,當(dāng)寫入文件為同一對象時(shí),并不會再將對象的內(nèi)容進(jìn)行存儲,而只是再次存儲一份引用,上面增加的5字節(jié)的存儲空間就是新增引用和一些控制信息的空間。反序列化時(shí),恢復(fù)引用關(guān)系,該存儲規(guī)則極大的節(jié)省了存儲空間。 在java中存在一個(gè)Cloneable接口,通過實(shí)現(xiàn)這個(gè)接口的類都會具備clone的能力,同時(shí)clone在內(nèi)存中進(jìn)行,在性能方面會比我們直接通過new生成對象要高一些,特別是一些大的對象的生成,性能提升相對比較明顯。 優(yōu)點(diǎn):java語言本省提供,使用比較方面和簡單 缺點(diǎn):不支持跨語言處理、想能相對不是很好,序列化以后產(chǎn)生的數(shù)據(jù)相對較大 XML序列化的好處在于可讀性好,方面閱讀和調(diào)試。但是序列化以后的字節(jié)碼文件比較大,而且效率不高,適應(yīng)于對性能不高,而且QPS較低的企業(yè)級內(nèi)部系統(tǒng)之間的數(shù)據(jù)交換的場景,同時(shí)XML又具有語言無慣性,所以還可以用于異構(gòu)系統(tǒng)之間的數(shù)據(jù)交換和協(xié)議。比如我們熟知的WebService,就是采用XML格式對數(shù)據(jù)進(jìn)行序列化的 JSON(JavaScriptObjectNotation)是一種輕量級的數(shù)據(jù)交換格式,相對于XML來說,JON的字節(jié)流較小,而且可讀性也非常好。現(xiàn)在JSON數(shù)據(jù)格式的其他運(yùn)用最普遍的。 Hessian是一個(gè)支持跨語言傳輸?shù)亩M(jìn)制序列化協(xié)議,相對于Java默認(rèn)的序列化機(jī)制來說,Hessian具有更好的性能和易用性,而且支持對重不同的語言,實(shí)際上Dubbo采用的就是Hessian序列化來實(shí)現(xiàn),只不過Dubbo對Hessian進(jìn)行重構(gòu),性能更高。 Protobuf是Google的一種數(shù)據(jù)交換格式,它獨(dú)立于語言、獨(dú)立于平臺。 Google提供了多種語言來實(shí)現(xiàn),比如Java、C、Go、Python,每一種實(shí)現(xiàn)都包含了相應(yīng)語言的編譯器和庫文件Protobuf使用比較廣泛,主要是空間開銷小和性能比較好,非常適合用于公司內(nèi)部對性能要求高的RPC調(diào)用。另外由于解析性能比較高,序列化以后數(shù)據(jù)量相對較少,所以也可以應(yīng)用在對象的持久化場景中但是但是要使用Protobuf會相對來說麻煩些,因?yàn)樗凶约旱恼Z法,有自己的編譯器。 ①序列化空間開銷,也就是序列化產(chǎn)生的結(jié)果大小,這個(gè)影響到傳輸?shù)男阅?/p> ②序列化過程中消耗的時(shí)長,序列化消耗時(shí)間過長影響到業(yè)務(wù)的響應(yīng)時(shí)間 ③序列化協(xié)議是否支持跨平臺,跨語言。因?yàn)楝F(xiàn)在的架構(gòu)更加靈活,如果存在異構(gòu)系統(tǒng)通信需求,那么這個(gè)是必須要考慮的 ④可擴(kuò)展性/兼容性,在實(shí)際業(yè)務(wù)開發(fā)中,系統(tǒng)往往需要隨著需求的快速迭代來實(shí)現(xiàn)快速更新,這就要求我們采用的序化協(xié)議基于良好的可擴(kuò)展性/兼容性,比如在現(xiàn)有的序列化數(shù)據(jù)結(jié)構(gòu)中新增一個(gè)業(yè)務(wù)字段,不會影響到現(xiàn)有的服務(wù) ⑤技術(shù)的流行程度,越流行的技術(shù)意味著使用的公司多,那么很多坑都已經(jīng)淌過并且得到了解決,技術(shù)解決方案也相對成熟 ⑥學(xué)習(xí)難度和易用性 ①對性能要求不高的場景,可以采用基于XML的SOAP協(xié)議 ②對性能和間接性有比較高要求的場景,那么Hessian、Protobuf、Thrift、Avro都可以 ③基于前后端分離,或者獨(dú)立的對外的api服務(wù),選用JSON是比較好的,對于調(diào)試、可讀性都很不錯(cuò) ④Avro設(shè)計(jì)理念偏于動態(tài)類型語言,那么這類的場景使用Avro是可以的使用Serializable接口需要注意的問題?
常見的序列化技術(shù)
序列化技術(shù)的選型