欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

1.什么是序列化

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

  • json
  • xml
  • yaml
  • Java Serialization

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

2.JAVA中的序列化

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

JAVA的序列化中有幾個注意點:

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

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

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

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

序列化Order的時候會報錯:

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

用transient修飾屬性:

可以看到屬性值不會被序列化出去,其會是默認值:

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

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

我們對同一個對象序列化兩次,然后輸出其屬性值:

819528be640a4caf8127f10ffa81d54c.png

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

a317890c83db4866b9775bf5ae6da2a5.png

2.4.serialVersionUID

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

serialVersionUID不會自動改變,而是留給程序員手動更改的一個版本號標志位。更改了序列化文件的程序員一并更改版本號提示后來的人文件被更改過。

如果在反序列化時,類的 serialVersionUID 與序列化時的版本號不匹配,那么會拋出 InvalidClassException 異常,表示類的版本不兼容,無法進行反序列化。

3.JDK序列化算法

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

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

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

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

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) {
                // 打印十六進制內(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 序列化文件的標識符。
  • 版本號:00 05 表示版本號為 5。
  • 對象數(shù)據(jù):73 72 00 0E 63 6F 6D 2E 65 72 79 69 2E 4F 72 64 65 72 是一個類描述符,指明被序列化對象所屬的類為 com.eryi.Order。
  • 對象數(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 是一個對象的實例數(shù)據(jù),包含了對象的狀態(tài)信息。
  • 對象數(shù)據(jù):4C 00 07 70 72 6F 64 75 63 74 是一個對象的實例變量的描述符,指明變量名為 product。
  • 對象數(shù)據(jù):74 00 12 4C 63 6F 6D 2F 65 72 79 69 2F 50 72 6F 64 75 63 74 3B 是一個字符串,表示變量值為 "com.eryi.Product"。
  • 對象數(shù)據(jù):78 70 74 00 03 34 35 36 是一個對象的實例變量的描述符,指明變量名為 xpt。
  • 對象數(shù)據(jù):73 72 00 10 63 6F 6D 2E 65 72 79 69 2E 50 72 6F 64 75 63 74 是一個類描述符,指明變量類型為 com.eryi.Product
  • 對象數(shù)據(jù):15 0D 2C B6 A0 EE 95 4F 02 00 02 是一個對象的實例數(shù)據(jù),包含了變量的狀態(tài)信息。
  • 對象數(shù)據(jù):4C 00 04 6E 61 6D 65 是一個對象的實例變量的描述符,指明變量名為 name
  • 對象數(shù)據(jù):71 00 7E 00 01 是一個字符串,表示變量值為 "name"。
  • 對象數(shù)據(jù):4C 00 05 70 72 69 63 65 是一個對象的實例變量的描述符,指明變量名為 price
  • 對象數(shù)據(jù):71 00 7E 00 01 是一個字符串,表示變量值為 "price"
  • 對象數(shù)據(jù):78 70 74 00 0C E6 B2 83 E5 B0 94 E6 B2 83 53 36 30 是一個對象的實例變量的描述符,指明變量名為 xpt
  • 對象數(shù)據(jù):74 00 03 33 30 57 是一個字符串,表示變量值為 "30W"。

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

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

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

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

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

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

相關(guān)文章

  • java文件操作代碼片斷實例實現(xiàn)統(tǒng)計文件中字母出現(xiàn)的個數(shù)功能

    java文件操作代碼片斷實例實現(xiàn)統(tǒng)計文件中字母出現(xiàn)的個數(shù)功能

    本文介紹java讀文件實例,實現(xiàn)統(tǒng)計某一目錄下每個文件中出現(xiàn)的字母個數(shù)、數(shù)字個數(shù)、空格個數(shù)及行數(shù),除此之外沒有其他字符,大家參考使用吧
    2014-01-01
  • Java中JSON字符串反序列化(動態(tài)泛型)

    Java中JSON字符串反序列化(動態(tài)泛型)

    文章討論了在定時任務(wù)中使用反射調(diào)用目標對象時處理動態(tài)參數(shù)的問題,通過將方法參數(shù)存儲為JSON字符串并進行反序列化,可以實現(xiàn)動態(tài)調(diào)用,然而,這種方式容易導致內(nèi)存溢出(OOM),這篇文章主要介紹了JSON字符串反序列化?動態(tài)泛型,需要的朋友可以參考下
    2024-12-12
  • Spring Boot結(jié)合IDEA自帶Maven插件如何快速切換profile

    Spring Boot結(jié)合IDEA自帶Maven插件如何快速切換profile

    IDEA是目前 Java 開發(fā)者中使用最多的開發(fā)工具,它有著簡約的設(shè)計風格,強大的集成工具,便利的快捷鍵,這篇文章主要介紹了Spring Boot結(jié)合IDEA自帶Maven插件快速切換profile,需要的朋友可以參考下
    2023-03-03
  • 為SpringBoot服務(wù)添加HTTPS證書的方法

    為SpringBoot服務(wù)添加HTTPS證書的方法

    這篇文章主要介紹了為SpringBoot服務(wù)添加HTTPS證書的方法,幫助大家更好的理解和使用springBoot框架,感興趣的朋友可以了解下
    2020-10-10
  • Spring-Data-JPA整合MySQL和配置的方法

    Spring-Data-JPA整合MySQL和配置的方法

    這篇文章主要介紹了Spring Data JPA整合MySQL和配置,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • 基于springboot的flowable工作流實戰(zhàn)流程分析

    基于springboot的flowable工作流實戰(zhàn)流程分析

    這篇文章主要介紹了基于springboot的flowable工作流實戰(zhàn)流程分析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • 詳解Spring Boot的GenericApplicationContext使用教程

    詳解Spring Boot的GenericApplicationContext使用教程

    這篇教程展示了如何在Spring應(yīng)用程序中使用GenericApplicationContext 。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • Spring?Security用戶定義?

    Spring?Security用戶定義?

    這篇文章主要介紹了Spring?Security用戶定義,大家都知道?Spring?Security的用戶定義有很多方式,其實主要有兩種,基于內(nèi)存的和基于數(shù)據(jù)庫的,下面我給大家簡單介紹一下這兩種方式,需要的朋友可以參考下
    2022-02-02
  • Java中l(wèi)ambda表達式的基本運用

    Java中l(wèi)ambda表達式的基本運用

    大家好,本篇文章主要講的是Java中l(wèi)ambda表達式的基本運用,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • FeignClient如何通過配置變量調(diào)用配置文件url

    FeignClient如何通過配置變量調(diào)用配置文件url

    這篇文章主要介紹了FeignClient如何通過配置變量調(diào)用配置文件url,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06

最新評論