為什么不建議使用 Java 自帶的序列化?


作者:rickiyang

出處:www.cnblogs.com/rickiyang/p/11074232.html

談到序列化我們自然想到 Java 提供的 Serializable 接口,在 Java 中我們如果需要序列化只需要繼承該接口就可以通過輸入輸出流進行序列化和反序列化。

但是在提供很用戶簡單的調用的同時他也存在很多問題:

1、無法跨語言

當我們進行跨應用之間的服務調用的時候如果另外一個應用使用c語言來開發,這個時候我們發送過去的序列化對象,別人是無法進行反序列化的因為其內部實現對於別人來說完全就是黑盒。

2、序列化之后的碼流太大

這個我們可以做一個實驗還是上一節中的Message類,我們分別用java的序列化和使用二進制編碼來做一個對比,下面我寫了一個測試類:

@Test
public void testSerializable(){
    String str = "哈哈,我是一條消息";
    Message msg = new Message((byte)0xAD,35,str);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
        ObjectOutputStream os = new ObjectOutputStream(out);
        os.writeObject(msg);
        os.flush();
        byte[] b = out.toByteArray();
        System.out.println("jdk序列化后的長度: "+b.length);
        os.close();
        out.close();


        ByteBuffer buffer = ByteBuffer.allocate(1024);
        byte[] bt = msg.getMsgBody().getBytes();
        buffer.put(msg.getType());
        buffer.putInt(msg.getLength());
        buffer.put(bt);
        buffer.flip();

        byte[] result = new byte[buffer.remaining()];
        buffer.get(result);
        System.out.println("使用二進制序列化的長度:"+result.length);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

輸出結果為:

我們可以看到差距是挺大的,目前的主流編解碼框架序列化之后的碼流也都比java序列化要小太多。

3、序列化效率

這個我們也可以做一個對比,還是上面寫的測試代碼我們循環跑100000次對比一下時間:

@Test
public void testSerializable(){
    String str = "哈哈,我是一條消息";
    Message msg = new Message((byte)0xAD,35,str);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
        long startTime = System.currentTimeMillis();
        for(int i = 0;i < 100000;i++){
            ObjectOutputStream os = new ObjectOutputStream(out);
            os.writeObject(msg);
            os.flush();
            byte[] b = out.toByteArray();
            /*System.out.println("jdk序列化后的長度: "+b.length);*/
            os.close();
            out.close();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("jdk序列化100000次耗時:" +(endTime - startTime));

        long startTime1 = System.currentTimeMillis();
        for(int i = 0;i < 100000;i++){
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            byte[] bt = msg.getMsgBody().getBytes();
            buffer.put(msg.getType());
            buffer.putInt(msg.getLength());
            buffer.put(bt);
            buffer.flip();

            byte[] result = new byte[buffer.remaining()];
            buffer.get(result);
            /*System.out.println("使用二進制序列化的長度:"+result.length);*/
        }
        long endTime1 = System.currentTimeMillis();
        System.out.println("使用二進制序列化100000次耗時:" +(endTime1 - startTime1));

    } catch (IOException e) {
        e.printStackTrace();
    }
}

結果為:

結果為毫秒數,這個差距也是不小的。

結合以上我們看到:目前的序列化過程中使用 Java 本身的肯定是不行,使用二進制編碼的話又的我們自己去手寫,所以為了讓我們少搬磚前輩們早已經寫好了工具讓我們調用,目前社區比較活躍的有 google 的 Protobuf 和Apache 的 Thrift。

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2021最新版)

2.終於靠開源項目弄到 IntelliJ IDEA 激活碼了,真香!

3.阿里 Mock 工具正式開源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式發布,全新顛覆性版本!

5.《Java開發手冊(嵩山版)》最新發布,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM