爲何不建議使用 Java 自帶的序列化?

做者:rickiyang

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

談到序列化咱們天然想到 Java 提供的 Serializable 接口,在 Java 中咱們若是須要序列化只須要繼承該接口就能夠經過輸入輸出流進行序列化和反序列化。java

可是在提供很用戶簡單的調用的同時他也存在不少問題:面試

一、沒法跨語言spring

當咱們進行跨應用之間的服務調用的時候若是另一個應用使用c語言來開發,這個時候咱們發送過去的序列化對象,別人是沒法進行反序列化的由於其內部實現對於別人來講徹底就是黑盒。intellij-idea

二、序列化以後的碼流太大框架

這個咱們能夠作一個實驗仍是上一節中的Message類,咱們分別用java的序列化和使用二進制編碼來作一個對比,下面我寫了一個測試類:ide

@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序列化要小太多。測試

三、序列化效率google

這個咱們也能夠作一個對比,仍是上面寫的測試代碼咱們循環跑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開發手冊(嵩山版)》最新發布,速速下載!

以爲不錯,別忘了隨手點贊+轉發哦!

相關文章
相關標籤/搜索