為什么不建議使用 Java 自帶的序列化?
作者:rickiyang
出處:www.cnblogs.com/rickiyang/p/11074232.html
談到序列化我們自然想到 Java 提供的 Serializable 接口,在 Java 中我們?nèi)绻枰蛄谢恍枰^承該接口就可以通過(guò)輸入輸出流進(jìn)行序列化和反序列化。
但是在提供很用戶簡(jiǎn)單的調(diào)用的同時(shí)他也存在很多問(wèn)題:
1、無(wú)法跨語(yǔ)言
當(dāng)我們進(jìn)行跨應(yīng)用之間的服務(wù)調(diào)用的時(shí)候如果另外一個(gè)應(yīng)用使用c語(yǔ)言來(lái)開(kāi)發(fā),這個(gè)時(shí)候我們發(fā)送過(guò)去的序列化對(duì)象,別人是無(wú)法進(jìn)行反序列化的因?yàn)槠鋬?nèi)部實(shí)現(xiàn)對(duì)于別人來(lái)說(shuō)完全就是黑盒。
2、序列化之后的碼流太大
@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序列化后的長(zhǎng)度: "+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("使用二進(jìn)制序列化的長(zhǎng)度:"+result.length);
} catch (IOException e) {
e.printStackTrace();
}
}

我們可以看到差距是挺大的,目前的主流編解碼框架序列化之后的碼流也都比java序列化要小太多。
3、序列化效率
這個(gè)我們也可以做一個(gè)對(duì)比,還是上面寫(xiě)的測(cè)試代碼我們循環(huán)跑100000次對(duì)比一下時(shí)間:
@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序列化后的長(zhǎng)度: "+b.length);*/
os.close();
out.close();
}
long endTime = System.currentTimeMillis();
System.out.println("jdk序列化100000次耗時(shí):" +(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("使用二進(jìn)制序列化的長(zhǎng)度:"+result.length);*/
}
long endTime1 = System.currentTimeMillis();
System.out.println("使用二進(jìn)制序列化100000次耗時(shí):" +(endTime1 - startTime1));
} catch (IOException e) {
e.printStackTrace();
}
}

結(jié)果為毫秒數(shù),這個(gè)差距也是不小的。
結(jié)合以上我們看到:
目前的序列化過(guò)程中使用 Java 本身的肯定是不行,使用二進(jìn)制編碼的話又的我們自己去手寫(xiě),所以為了讓我們少搬磚前輩們?cè)缫呀?jīng)寫(xiě)好了工具讓我們調(diào)用,目前社區(qū)比較活躍的有 google 的 Protobuf 和 Apache 的 Thrift。
PS:如果覺(jué)得我的分享不錯(cuò),歡迎大家隨手點(diǎn)贊、轉(zhuǎn)發(fā)。
—————END————— 推薦閱讀: 再見(jiàn)!收費(fèi)的 XShell,我改用這款國(guó)產(chǎn)良心工具! 一個(gè)幫你輕松搞定第三方登陸的 Java 開(kāi)源組件 拒絕 ! = null ,大神有更好的方法! 一個(gè)低級(jí)錯(cuò)誤,生產(chǎn)數(shù)據(jù)庫(kù)崩潰了將近半個(gè)小時(shí)..... 重磅推薦:一套開(kāi)源的網(wǎng)校系統(tǒng),附源碼! IDEA 2021.1 的 Win 和 Mac 快捷鍵大全! 最近面試BAT,整理一份面試資料《Java面試BAT通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。 獲取方式:關(guān)注公眾號(hào)并回復(fù) java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。 明天見(jiàn)(??ω??)??

