最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解JAVA序列化及實(shí)際應(yīng)用場(chǎng)景分析

 更新時(shí)間:2024年12月06日 09:53:07   作者:_BugMan  
序列化就是將對(duì)象轉(zhuǎn)換為可以存儲(chǔ)或傳輸?shù)男问?以實(shí)現(xiàn)對(duì)象持久化存儲(chǔ)到磁盤中,或者在網(wǎng)絡(luò)中傳輸,這篇文章介紹JAVA序列化及實(shí)際應(yīng)用場(chǎng)景分析,感興趣的朋友跟隨小編一起看看吧

1.什么是序列化

序列化就是將對(duì)象轉(zhuǎn)換為可以存儲(chǔ)或傳輸?shù)男问?,以?shí)現(xiàn)對(duì)象持久化存儲(chǔ)到磁盤中,或者在網(wǎng)絡(luò)中傳輸。要將對(duì)象轉(zhuǎn)為可以存儲(chǔ)或傳輸?shù)男问?,首先就要用一種統(tǒng)一的標(biāo)準(zhǔn)來描述對(duì)象,這樣序列化的對(duì)象才能被反序列化出來。不同的序列化算法就是用不同的標(biāo)準(zhǔn)來描述對(duì)象,序列化算法很多,這里舉幾個(gè)常見的:

  • json
  • xml
  • yaml
  • Java Serialization

前三種見名知意,就是分別用json、xml、yaml來描述對(duì)象,第四種Java Serialization是JDK默認(rèn)的序列化算法,其使用了一種稱為 Java Object Serialization Stream Protocol 的二進(jìn)制格式來描述JAVA對(duì)象。

2.JAVA中的序列化

JDK種提供了Serializable接口用來聲明哪些類可以被序列化,提供了ObjectOutputStream、ObjectOutputStream來進(jìn)行序列化和反序列化。

JAVA的序列化中有幾個(gè)注意點(diǎn):

  • 成員變量必須可序列化
  • transient關(guān)鍵字,可避免被序列化
  • 無(wú)法更新狀態(tài)
  • serialVersionUID

2.1.成員變量必須可序列化

如果所要序列化的對(duì)象的成員屬性中含有對(duì)其他對(duì)象的引用,要求所引用的對(duì)象也必須是可序列化的(實(shí)現(xiàn)serializable接口),否則會(huì)序列化失敗。

訂單對(duì)象中包含一個(gè)產(chǎn)品對(duì)象,Order實(shí)現(xiàn)了序列化接口,但是product沒有實(shí)現(xiàn)序列化接口:

序列化Order的時(shí)候會(huì)報(bào)錯(cuò):

2.2.transient關(guān)鍵字,可避免被序列化

用transient修飾屬性:

可以看到屬性值不會(huì)被序列化出去,其會(huì)是默認(rèn)值:

2.3.無(wú)法更新狀態(tài)

由于java序利化算法不會(huì)重復(fù)序列化同一個(gè)對(duì)象,如果對(duì)象的內(nèi)容更改后,,再次序列化,并不會(huì)再次將此對(duì)象轉(zhuǎn)換為字節(jié)序列。

我們對(duì)同一個(gè)對(duì)象序列化兩次,然后輸出其屬性值:

819528be640a4caf8127f10ffa81d54c.png

可以看到其實(shí)只有第一次序列化是生效的:

a317890c83db4866b9775bf5ae6da2a5.png

2.4.serialVersionUID

序列化版本號(hào),類似于樂觀鎖中的版本號(hào),用來保證序列化后的字節(jié)序列沒有被改動(dòng)過,反序列化回來后和原來的程序是兼容的。

serialVersionUID不會(huì)自動(dòng)改變,而是留給程序員手動(dòng)更改的一個(gè)版本號(hào)標(biāo)志位。更改了序列化文件的程序員一并更改版本號(hào)提示后來的人文件被更改過。

如果在反序列化時(shí),類的 serialVersionUID 與序列化時(shí)的版本號(hào)不匹配,那么會(huì)拋出 InvalidClassException 異常,表示類的版本不兼容,無(wú)法進(jìn)行反序列化。

3.JDK序列化算法

Java Object Serialization Stream Protocol規(guī)定整個(gè)對(duì)象序列化后的文件由三部分組成:

  • 頭部(Header):包含魔數(shù)(Magic Number)和版本號(hào)(Version Number)。魔數(shù)標(biāo)識(shí)了該流是 Java 序列化流,版本號(hào)用于指定序列化協(xié)議的版本。
  • 類描述符表(Class Descriptor Table):包含了序列化流中所引用的類的描述符信息。每個(gè)類描述符包括類的名稱、序列化編號(hào)、序列化版本號(hào)等信息。
  • 對(duì)象數(shù)據(jù)(Object Data):按照序列化順序包含了被序列化對(duì)象的狀態(tài)信息。這包括了對(duì)象的實(shí)例變量、類信息等。

以上一節(jié)我們?cè)贒盤下生成了一個(gè)名叫Order.txt的序列化文件為例,我們來讀一讀JAVA的序列化文件。

要注意的是如果直接打開,因?yàn)榫幋a的原因看見的會(huì)是亂碼,需要用16進(jìn)制的方式,打開它來看看,要注意的是普通的文本工具都沒辦法用16進(jìn)制的方式直接打開文件,這里我們用代碼來將文本中的內(nèi)容以16進(jìn)制的方式輸出,代碼如下:

public static void main(String[] args) throws IOException {
        displayFileInHex("D:\\Order.txt");
    }
    private static void displayFileInHex(String filePath) throws IOException {
        try (FileInputStream fileIn = new FileInputStream(filePath)) {
            int bytesRead;
            byte[] buffer = new byte[16];
            while ((bytesRead = fileIn.read(buffer)) != -1) {
                // 打印十六進(jìn)制內(nèi)容
                for (int i = 0; i < bytesRead; i++) {
                    System.out.printf("%02X ", buffer[i]);
                }
                // 填充缺失的位置
                if (bytesRead < 16) {
                    int missingBytes = 16 - bytesRead;
                    for (int i = 0; i < missingBytes; i++) {
                        System.out.print("   ");
                    }
                }
                System.out.println("\n");
            }
        }
    }

輸出結(jié)果:

用Java Object Serialization Stream Protocol來解析一下上面的字節(jié)內(nèi)容:

  • 頭部(Header):AC ED 表示 Java 序列化文件的標(biāo)識(shí)符。
  • 版本號(hào):00 05 表示版本號(hào)為 5。
  • 對(duì)象數(shù)據(jù):73 72 00 0E 63 6F 6D 2E 65 72 79 69 2E 4F 72 64 65 72 是一個(gè)類描述符,指明被序列化對(duì)象所屬的類為 com.eryi.Order。
  • 對(duì)象數(shù)據(jù):9D F0 BD D3 7C 8B DA 85 02 00 02 4C 00 0B 6F 72 64 65 72 4E 75 6D 62 65 72 74 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 是一個(gè)對(duì)象的實(shí)例數(shù)據(jù),包含了對(duì)象的狀態(tài)信息。
  • 對(duì)象數(shù)據(jù):4C 00 07 70 72 6F 64 75 63 74 是一個(gè)對(duì)象的實(shí)例變量的描述符,指明變量名為 product
  • 對(duì)象數(shù)據(jù):74 00 12 4C 63 6F 6D 2F 65 72 79 69 2F 50 72 6F 64 75 63 74 3B 是一個(gè)字符串,表示變量值為 "com.eryi.Product"
  • 對(duì)象數(shù)據(jù):78 70 74 00 03 34 35 36 是一個(gè)對(duì)象的實(shí)例變量的描述符,指明變量名為 xpt
  • 對(duì)象數(shù)據(jù):73 72 00 10 63 6F 6D 2E 65 72 79 69 2E 50 72 6F 64 75 63 74 是一個(gè)類描述符,指明變量類型為 com.eryi.Product
  • 對(duì)象數(shù)據(jù):15 0D 2C B6 A0 EE 95 4F 02 00 02 是一個(gè)對(duì)象的實(shí)例數(shù)據(jù),包含了變量的狀態(tài)信息。
  • 對(duì)象數(shù)據(jù):4C 00 04 6E 61 6D 65 是一個(gè)對(duì)象的實(shí)例變量的描述符,指明變量名為 name。
  • 對(duì)象數(shù)據(jù):71 00 7E 00 01 是一個(gè)字符串,表示變量值為 "name"。
  • 對(duì)象數(shù)據(jù):4C 00 05 70 72 69 63 65 是一個(gè)對(duì)象的實(shí)例變量的描述符,指明變量名為 price
  • 對(duì)象數(shù)據(jù):71 00 7E 00 01 是一個(gè)字符串,表示變量值為 "price"。
  • 對(duì)象數(shù)據(jù):78 70 74 00 0C E6 B2 83 E5 B0 94 E6 B2 83 53 36 30 是一個(gè)對(duì)象的實(shí)例變量的描述符,指明變量名為 xpt
  • 對(duì)象數(shù)據(jù):74 00 03 33 30 57 是一個(gè)字符串,表示變量值為 "30W"

4.序列化在實(shí)際中的一些應(yīng)用

首先我們要知道序列化是可以跨JVM的,JDK的序列化算法只是規(guī)定了標(biāo)準(zhǔn),所以可以在一個(gè)JVM上序列化,然后在另一個(gè)JVM中進(jìn)行反序列化,這也就是說序列化可以用來進(jìn)行通信時(shí)的數(shù)據(jù)傳輸。

一些自定義的將對(duì)象直接存為二進(jìn)制或者其它進(jìn)制的序列化協(xié)議(比如就上文的JDK序列化算法)在數(shù)據(jù)傳輸上具有很好的性能優(yōu)勢(shì)。因?yàn)橹苯訉?duì)象轉(zhuǎn)為了二進(jìn)制(其它進(jìn)制一樣的道理),接收端收到數(shù)據(jù)后直接就可以通過二進(jìn)制數(shù)據(jù)流反序列化得到對(duì)象。如果是以JSON之類的文本結(jié)構(gòu)傳輸數(shù)據(jù),那么接收端收到數(shù)據(jù)后要首先將二進(jìn)制數(shù)據(jù)流轉(zhuǎn)為文本結(jié)構(gòu),然后再解析文本結(jié)構(gòu)將其轉(zhuǎn)為對(duì)象,整個(gè)過程就要慢很多。

由于上面的原因,在很多追求高性能的通信場(chǎng)景,經(jīng)常會(huì)自定義序列化協(xié)議。比如dubbo,dubbo作為以高性能著稱的RPC框架,其高性能有一方面就體現(xiàn)在使用了序列化上。dubbo自定義了報(bào)文和序列化協(xié)議,然后通過序列化的方式將數(shù)據(jù)直接塞進(jìn)自定義的報(bào)文結(jié)構(gòu)中,接收端收到后直接反序列化就可以得到數(shù)據(jù)。

同時(shí),序列化又存在安全隱患,由于serialVersionUID和數(shù)據(jù)沒有任何關(guān)系,修改屬性的數(shù)據(jù)值后,仍然可以反序列化回來,而且任何JVM拿到序列化的數(shù)據(jù)都可以進(jìn)行反序列化,會(huì)存在數(shù)據(jù)被攔截然后惡意修改的風(fēng)險(xiǎn)。不過這個(gè)問題并不是序列化所獨(dú)有的問題,只要是沒有加密機(jī)制的通信協(xié)議都會(huì)存在這個(gè)問題,相比于同樣是透明傳輸?shù)腍TTP來說,用序列化在JAVA EE體系中傳數(shù)據(jù)對(duì)象確實(shí)性能更優(yōu)。

到此這篇關(guān)于詳解JAVA序列化的文章就介紹到這了,更多相關(guān)java序列化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

阿尔山市| 苍溪县| 乐亭县| 金溪县| 八宿县| 万盛区| 红原县| 大足县| 荆门市| 宜昌市| 莱阳市| 梓潼县| 三台县| 灯塔市| 姚安县| 济阳县| 阳泉市| 崇左市| 榆树市| 泸水县| 尉氏县| 大庆市| 元朗区| 伊宁县| 沧州市| 黑水县| 旌德县| 伊吾县| 东兰县| 房产| 扶沟县| 太原市| 安阳市| 小金县| 阳原县| 玉山县| 沐川县| 华亭县| 房产| 福建省| 吴桥县|