幾種Java常用序列化框架的選型與對比

2022-01-01 阿里技術

收錄於話題 #Java 85個

序列化與反序列化是我們日常數據持久化和網絡傳輸中經常使用的技術,但是目前各種序列化框架讓人眼花繚亂,不清楚什麼場景到底採用哪種序列化框架。本文會將業界開源的序列化框架進行對比測試,分別從通用性、易用性、可擴展性、性能和數據類型與Java語法支持五方面給出對比測試。下面分別對JDK Serializable、FST、Kryo、Protobuf、Thrift、Hession和Avro進行對比測試。JDK Serializable是Java自帶的序列化框架,我們只需要實現java.io.Serializable或java.io.Externalizable接口,就可以使用Java自帶的序列化機制。實現序列化接口只是表示該類能夠被序列化/反序列化,我們還需要藉助I/O操作的ObjectInputStream和ObjectOutputStream對對象進行序列化和反序列化。下面是使用JDK 序列化框架進行編解碼的Demo:
public static byte[] encoder(Object ob) throws Exception{        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);    objectOutputStream.writeObject(ob);    byte[] result = byteArrayOutputStream.toByteArray();        objectOutputStream.close();    byteArrayOutputStream.close();    return result;}public static <T> T decoder(byte[] bytes) throws Exception {    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);    ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);    T object = (T) objectInputStream.readObject();    objectInputStream.close();    byteArrayInputStream.close();    return object;}

由於是Java內置序列化框架,所以本身是不支持跨語言序列化與反序列化。作為Java內置序列化框架,無序引用任何外部依賴即可完成序列化任務。但是JDK Serializable在使用上相比開源框架難用許多,可以看到上面的編解碼使用非常生硬,需要藉助ByteArrayOutputStream和ByteArrayInputStream才可以完整字節的轉換。JDK Serializable中通過serialVersionUID控制序列化類的版本,如果序列化與反序列化版本不一致,則會拋出java.io.InvalidClassException異常信息,提示序列化與反序列化SUID不一致。
java.io.InvalidClassException: com.yjz.serialization.java.UserInfo; local class incompatible: stream classdesc serialVersionUID = -5548195544707231683, local class serialVersionUID = -5194320341014913710

上面這種情況,是由於我們沒有定義serialVersionUID,而是由JDK自動hash生成的,所以序列化與反序列化前後結果不一致。但是我們可以通過自定義serialVersionUID方式來規避掉這種情況(序列化前後都是使用定義的serialVersionUID),這樣JDK Serializable就可以支持欄位擴展了。
private static final long serialVersionUID = 1L;

JDK Serializable是Java自帶的序列化框架,但是在性能上其實一點不像親生的。下面測試用例是我們貫穿全文的一個測試實體。
public class MessageInfo implements Serializable {
private String username; private String password; private int age; private HashMap<String,Object> params; ... public static MessageInfo buildMessage() { MessageInfo messageInfo = new MessageInfo(); messageInfo.setUsername("abcdefg"); messageInfo.setPassword("123456789"); messageInfo.setAge(27); Map<String,Object> map = new HashMap<>(); for(int i = 0; i< 20; i++) { map.put(String.valueOf(i),"a"); } return messageInfo; }}

使用JDK序列化後字節大小為:432。光看這組數字也許不會感覺到什麼,之後我們會拿這個數據和其它序列化框架進行對比。
我們對該測試用例進行1000萬次序列化,然後計算時間總和:1000萬序列化耗時(ms)1000萬反序列化耗時(ms)3895296508由於JDK Serializable是Java語法原生序列化框架,所以基本都能夠支持Java數據類型和語法。
JDK8種基礎類型支持List集合類支持Set集合類支持Queue集合類支持Map映射大部分支持(WeakHashMap不支持)自定義類類型支持枚舉類型支持WeakHashMap沒有實現Serializable接口。
JDK對象為null支持沒有無參構造函數支持static內部類支持(static內部類需要實現序列化接口)非static內部類支持,但是外部類也需要實現序列化接口局部內部類支持匿名內部類支持Lambda表達式修改代碼可以支持,看注1閉包支持異常類支持
Runnable runnable = () -> System.out.println("Hello");

com.yjz.serialization.SerializerFunctionTest$$Lambda$1/189568618

原因就是我們Runnable的Lambda並沒有實現Serializable接口。我們可以做如下修改,即可支持Lambda表達式序列化。
Runnable runnable = (Runnable & Serializable) () -> System.out.println("Hello");

FST(fast-serialization)是完全兼容JDK序列化協議的Java序列化框架,它在序列化速度上能達到JDK的10倍,序列化結果只有JDK的1/3。目前FST的版本為2.56,在2.17版本之後提供了對Android的支持。下面是使用FST序列化的Demo,FSTConfiguration是線程安全的,但是為了防止頻繁調用時其成為性能瓶頸,一般會使用TreadLocal為每個線程分配一個FSTConfiguration。
private final ThreadLocal<FSTConfiguration> conf = ThreadLocal.withInitial(() -> {      FSTConfiguration conf = FSTConfiguration.createDefaultConfiguration();      return conf;  });
public byte[] encoder(Object object) {    return conf.get().asByteArray(object);}
public <T> T decoder(byte[] bytes) {    Object ob = conf.get().asObject(bytes);    return (T)ob;}

FST同樣是針對Java而開發的序列化框架,所以也不存在跨語言特性。在易用性上,FST可以說能夠甩JDK Serializable幾條街,語法極其簡潔,FSTConfiguration封裝了大部分方法。FST通過@Version註解能夠支持新增欄位與舊的數據流兼容。對於新增的欄位都需要通過@Version註解標識,沒有版本注釋意味著版本為0。
private String origiField;@Version(1)private String addField;

綜合來看,FST在擴展性上面雖然支持,但是用起來還是比較繁瑣的。使用FST序列化上面的測試用例,序列化後大小為:172,相比JDK序列化的432 ,將近減少了1/3。下面我們再看序列化與反序列化的時間開銷。1000萬序列化耗時(ms)1000萬反序列化耗時(ms)1358719031我們可以優化一下FST,將循環引用判斷關閉,並且對序列化類進行餘註冊。
private static final ThreadLocal<FSTConfiguration> conf = ThreadLocal.withInitial(() -> {      FSTConfiguration conf = FSTConfiguration.createDefaultConfiguration();      conf.registerClass(UserInfo.class);      conf.setShareReferences(false);      return conf;  });

1000萬序列化耗時(ms)1000萬反序列化耗時(ms)760917792可以看到序列化時間將近提升了2倍,但是通過優化後的序列化數據大小增長到了191 。FST是基於JDK序列化框架而進行開發的,所以在數據類型和語法上和Java支持性一致。
FST8種基礎類型支持List集合類支持Set集合類支持Queue集合類支持Map映射大部門支持(WeakHashMap不支持)自定義類類型支持枚舉類型支持
FST對象為null支持沒有無參構造函數支持static內部類支持(static內部類需要實現序列化接口)非static內部類支持,但是外部類也需要實現序列化接口局部內部類支持匿名內部類支持Lambda表達式‍修改代碼可以支持(同JDK)閉包支持異常類支持Kryo一個快速有效的Java二進位序列化框架,它依賴底層ASM庫用於字節碼生成,因此有比較好的運行速度。Kryo的目標就是提供一個序列化速度快、結果體積小、API簡單易用的序列化框架。Kryo支持自動深/淺拷貝,它是直接通過對象->對象的深度拷貝,而不是對象->字節->對象的過程。
private static final ThreadLocal<Kryo> kryoLocal = ThreadLocal.withInitial(() -> {        Kryo kryo = new Kryo();            kryo.setRegistrationRequired(false);        return kryo;    });
public static byte[] encoder(Object object) { Output output = new Output(); kryoLocal.get().writeObject(output,object); output.flush(); return output.toBytes(); }
public static <T> T decoder(byte[] bytes) { Input input = new Input(bytes); Object ob = kryoLocal.get().readClassAndObject(input); return (T) ob; }

需要注意的是使用Output.writeXxx時候一定要用對應的Input.readxxx,比如Output.writeClassAndObject()要與Input.readClassAndObject()。

首先Kryo官網說自己是一款Java二進位序列化框架,其次在網上搜了一遍沒有看到Kryo的跨語言使用,只是一些文章提及了跨語言使用非常複雜,但是沒有找到其它語言的相關實現。在使用方式上Kryo提供的API也是非常簡潔易用,Input和Output封裝了你幾乎能夠想到的所有流操作。Kryo提供了豐富的靈活配置,比如自定義序列化器、設置默認序列化器等等,這些配置使用起來還是比較費勁的。Kryo默認序列化器FiledSerializer是不支持欄位擴展的,如果想要使用擴展序列化器則需要配置其它默認序列化器。
private static final ThreadLocal<Kryo> kryoLocal = ThreadLocal.withInitial(() -> {        Kryo kryo = new Kryo();        kryo.setRegistrationRequired(false);        kryo.setDefaultSerializer(TaggedFieldSerializer.class);        return kryo;    });

使用Kryo測試上面的測試用例,Kryo序列化後的字節大小為172 ,和FST未經優化的大小一致。時間開銷如下:1000萬序列化時間開銷(ms)1000萬反序列化時間開銷(ms)1355014315我們同樣關閉循環引用配置和預註冊序列化類,序列化後的字節大小為120,因為這時候類序列化的標識是使用的數字,而不是類全名。使用的是時間開銷如下:
1000萬序列化時間開銷(ms)1000萬反序列化時間開銷(ms)1179911584Kryo對於序列化類的基本要求就是需要含有無參構造函數,因為反序列化過程中需要使用無參構造函數創建對象。
Kryo8種基礎類型支持List集合類支持Set集合類支持Queue集合類部分支持(ArrayBlockingQueue不支持)Map映射支持自定義類類型支持枚舉類型支持
Kryo對象為null支持沒有無參構造函數不支持static內部類支持非static內部類不支持局部內部類支持匿名內部類支持Lambda表達式‍不支持閉包支持異常類不支持(StackOverflowError)Protocol buffer是一種語言中立、平臺無關、可擴展的序列化框架。Protocol buffer相較於前面幾種序列化框架而言,它是需要預先定義Schema的。
syntax = "proto3";
option java_package = "com.yjz.serialization.protobuf3";
message MessageInfo{ string username = 1; string password = 2; int32 age = 3; map<string,string> params = 4;}

protoc --java_out=./src/main/java message.proto

byte[] bytes = MessageInfo.toByteArray()MessageInfo messageInfo = Message.MessageInfo.parseFrom(bytes);

protobuf設計之初的目標就是能夠設計一款與語言無關的序列化框架,它目前支持了Java、Python、C++、Go、C#等,並且很多其它語言都提供了第三方包。所以在通用性上,protobuf是非常給力的。protobuf需要使用IDL來定義Schema描述文件,定義完描述文件後,我們可以直接使用protoc來直接生成序列化與反序列化代碼。所以,在使用上只需要簡單編寫描述文件,就可以使用protobuf了。可擴展性同樣是protobuf設計之初的目標之一,我們可以非常輕鬆的在.proto文件進行修改。新增欄位:對於新增欄位,我們一定要保證新增欄位要有對應的默認值,這樣才能夠與舊代碼交互。相應的新協議生成的消息,可以被舊協議解析。刪除欄位:刪除欄位需要注意的是,對應的欄位、標籤不能夠在後續更新中使用。為了避免錯誤,我們可以通過reserved規避帶哦。
message userinfo{    reserved 3,7;    reserved "age","sex" }

protobuf在數據兼容性上也非常友好,int32、unit32、int64、unit64、bool是完全兼容的,所以我們可以根據需要修改其類型。通過上面來看,protobuf在擴展性上做了很多,能夠很友好的支持協議擴展。我們同樣使用上面的實例來進行性能測試,使用protobuf序列化後的字節大小為 192,下面是對應的時間開銷。1000萬數據序列化耗時(ms)1000萬數據反序列化耗時(ms)1423530694可以看出protobuf的反序列化性能要比FST、Kryo差一些。
Protobuf使用IDL定義Schema所以不支持定義Java方法,下面序列化變量的測試:
Protobuf8種基礎類型基本支持(無byte、shot、char)List集合類支持Set集合類支持Queue集合類支持Map映射支持自定義類類型支持枚舉類型支持註:List、Set、Queue通過protobuf repeated定義測試的。只要實現Iterable接口的類都可以使用repeated列表。
Thrift是由Facebook實現的一種高效的、支持多種語言的遠程服務調用框架,即RPC(Remote Procedure Call)。後來Facebook將Thrift開源到Apache。可以看到Thrift是一個RPC框架,但是由於Thrift提供了多語言之間的RPC服務,所以很多時候被用於序列化中。使用Thrift實現序列化主要分為三步,創建thrift IDL文件、編譯生成Java代碼、使用TSerializer和TDeserializer進行序列化和反序列化。(1)使用Thrift IDL定義thrift文件:
namespace java com.yjz.serialization.thrift
struct MessageInfo{ 1: string username; 2: string password; 3: i32 age; 4: map<string,string> params;}

thrift --gen java message.thrift

(3)使用TSerializer和TDeserializer進行編解碼:
  public static byte[] encoder(MessageInfo messageInfo) throws Exception{        TSerializer serializer = new TSerializer();        return serializer.serialize(messageInfo);    }    public static MessageInfo decoder(byte[] bytes) throws Exception{        TDeserializer deserializer = new TDeserializer();        MessageInfo messageInfo = new MessageInfo();        deserializer.deserialize(messageInfo,bytes);        return messageInfo;    }

Thrift和protobuf類似,都需要使用IDL定義描述文件,這是目前實現跨語言序列化/RPC的一種有效方式。Thrift目前支持 C++、Java、Python、PHP、Ruby、 Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk、OCaml、Delphi等語言,所以可以看到Thrift具有很強的通用性。Thrift在易用性上和protobuf類似,都需要經過三步:使用IDL編寫thrift文件、編譯生成Java代碼和調用序列化與反序列化方法。protobuf在生成類中已經內置了序列化與反序列化方法,而Thrift需要單獨調用內置序列化器來進行編解碼。Thrift支持欄位擴展,在擴展欄位過程中需要注意以下問題:上面的測試用例,使用Thrift序列化後的字節大小為:257,下面是對應的序列化時間與反序列化時間開銷:1000萬序列化時間開銷(ms)1000萬反序列化時間開銷(ms)2863420722Thrift在序列化和反序列化的時間開銷總和上和protobuf差不多,protobuf在序列化時間上更佔優勢,而Thrift在反序列化上有自己的優勢。
數據類型支持:由於Thrift使用IDL來定義序列化類,所以能夠支持的數據類型就是Thrift數據類型。Thrift所能夠支持的Java數據類型:

8中基礎數據類型,沒有short、char,只能使用double和String代替。

集合類型,支持List、Set、Map,不支持Queue。

自定義類類型(struct類型)。

枚舉類型。

字節數組。

Hessian是caucho公司開發的輕量級RPC(Remote Procedure Call)框架,它使用HTTP協議傳輸,使用Hessian二進位序列化。Hessian由於其支持跨語言、高效的二進位序列化協議,被經常用於序列化框架使用。Hessian序列化協議分為Hessian1.0和Hessian2.0,Hessian2.0協議對序列化過程進行了優化(優化內容待看),在性能上相較Hessian1.0有明顯提升。使用Hessian序列化非常簡單,只需要通過HessianInput和HessianOutput即可完成對象的序列化,下面是Hessian序列化的Demo:
public static <T> byte[] encoder2(T obj) throws Exception{        ByteArrayOutputStream bos = new ByteArrayOutputStream();        Hessian2Output hessian2Output = new Hessian2Output(bos);        hessian2Output.writeObject(obj);        return bos.toByteArray();    }
public static <T> T decoder2(byte[] bytes) throws Exception { ByteArrayInputStream bis = new ByteArrayInputStream(bytes); Hessian2Input hessian2Input = new Hessian2Input(bis); Object obj = hessian2Input.readObject(); return (T) obj; }

Hessian與Protobuf、Thrift一樣,支持跨語言RPC通信。Hessian相比其它跨語言PRC框架的一個主要優勢在於,它不是採用IDL來定義數據和服務,而是通過自描述來完成服務的定義。目前Hessian已經實現了語言包括:Java、Flash/Flex、Python、C++、.Net/C#、D、Erlang、PHP、Ruby、Object-C。相較於Protobuf和Thrift,由於Hessian不需要通過IDL來定義數據和服務,對於序列化的數據只需要實現Serializable接口即可,所以使用上相比Protobuf和Thrift更加容易。Hession序列化類雖然需要實現Serializable接口,但是它並不受serialVersionUID影響,能夠輕鬆支持欄位擴展。

修改欄位名稱:反序列化後新欄位名稱為null或0(受類型影響)。

新增欄位:反序列化後新增欄位為null或0(受類型影響)。

刪除欄位:能夠正常反序列化。

修改欄位類型:如果欄位類型兼容能夠正常反序列化,如果不兼容則直接拋出異常。

使用Hessian1.0協議序列化上面的測試用例,序列化結果大小為277。使用Hessian2.0序列化協議,序列化結果大小為178。
1000萬序列化時間開銷(ms)1000萬反序列化時間開銷(ms)Hessian1.057648‍55261Hessian2.03882317682可以看到Hessian1.0的無論在序列化後體積大小,還是在序列化、反序列化時間上都比Hessian2.0相差很遠。由於Hession使用Java自描述序列化類,所以Java原生數據類型、集合類、自定義類、枚舉等基本都能夠支持(SynchronousQueue不支持),Java語法結構也能夠很好的支持。Avro是一個數據序列化框架。它是Apache Hadoop下的一個子項目,由Doug Cutting主導Hadoop過程中開發的數據序列化框架。Avro在設計之初就用於支持數據密集型應用,很適合遠程或本地大規模數據交換和存儲。
{    "namespace": "com.yjz.serialization.avro",    "type": "record",    "name": "MessageInfo",    "fields": [        {"name": "username","type": "string"},        {"name": "password","type": "string"},        {"name": "age","type": "int"},        {"name": "params","type": {"type": "map","values": "string"}        }    ]}

(2)使用avro-tools.jar編譯生成Java代碼(或maven編譯生成):
java -jar avro-tools-1.8.2.jar compile schema src/main/resources/avro/Message.avsc ./src/main/java

(3)藉助BinaryEncoder和BinaryDecoder進行編解碼:
public static  byte[] encoder(MessageInfo obj) throws Exception{        DatumWriter<MessageInfo> datumWriter = new SpecificDatumWriter<>(MessageInfo.class);        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();        BinaryEncoder binaryEncoder = EncoderFactory.get().directBinaryEncoder(outputStream,null);        datumWriter.write(obj,binaryEncoder);        return outputStream.toByteArray();    }
public static MessageInfo decoder(byte[] bytes) throws Exception{ DatumReader<MessageInfo> datumReader = new SpecificDatumReader<>(MessageInfo.class); BinaryDecoder binaryDecoder = DecoderFactory.get().directBinaryDecoder(new ByteArrayInputStream(bytes),null); return datumReader.read(new MessageInfo(),binaryDecoder); }

Avro通過Schema定義數據結構,目前支持Java、C、C++、C#、Python、PHP和Ruby語言,所以在這些語言之間Avro具有很好的通用性。Avro對於動態語言無需生成代碼,但對於Java這類靜態語言,還是需要使用avro-tools.jar來編譯生成Java代碼。在Schema編寫上,個人感覺相比Thrift、Protobuf更加複雜。

給所有field定義default值。如果某field沒有default值,以後將不能刪除該field。

如果要新增field,必須定義default值。

不能修改field type。

不能修改field name,不過可以通過增加alias解決。

使用Avro生成代碼序列化之後的結果為:111。下面是使用Avro序列化的時間開銷:
1000萬序列化時間開銷(ms)1000萬序反列化時間開銷(ms)生成Java代碼2656545383Avro需要使用Avro所支持的數據類型來編寫Schema信息,所以能夠支持的Java數據類型即為Avro所支持的數據類型。Avro支持數據類型有:基礎類型(null、boolean、int、long、float、double、bytes、string),複雜數據類型(Record、Enum、Array、Map、Union、Fixed)。Avro自動生成代碼,或者直接使用Schema,不能支持在序列化類中定義java方法。下面是從通用性上對比各個序列化框架,可以看出Protobuf在通用上是最佳的,能夠支持多種主流變成語言。序列化框架通用性JDK Serializer只適用於JavaFST只適用於JavaKryo主要適用於Java(可複雜支持跨語言)Protocol buffer支持多種語言Thrift支持多種語言Hessian支持多種語言Avro支持多種語言下面是從API使用的易用性上面來對比各個序列化框架,可以說除了JDK Serializer外的序列化框架都提供了不錯API使用方式。序列化框架易用性JDK Serializer使用語法過於生硬FST使用簡潔,FSTConfiguration提供了序列化與反序列化的方法Kryo使用簡潔,Input/Output封裝了幾乎所有能有需要的流方法Protocol buffer稍微複雜。需要編寫所需序列化類的proto文件,然後編譯生成Java代碼。但是自動生成Java類,包含了序列化與反序列化方法Thrift稍微複雜。需要編寫所需的序列化類的thrift文件,然後編譯生成Java代碼。然後通過TSerializer和TDserializer進行序列化與反序列化Hessian使用簡單,在跨語言的基礎上不需要使用IDLAvro使用較複雜。相較於Protobuf和Thrift來說,對於一些靜態語言無序生成代碼。但是對於Java來一般還需要生成代碼,並且Avro提供的API不是很友好下面是各個序列化框架的可擴展性對比,可以看到Protobuf的可擴展性是最方便、自然的。其它序列化框架都需要一些配置、註解等操作。序列化框架可擴展性JDK Serializer自定義serialVersionUID,保證序列化前後VUID一致即可FST通過@Version控制版本,新增欄位需要修改Version版本Kryo默認序列化器不支持欄位擴展,需要修改默認序列化器或自己實現序列化器Protocol buffer支持欄位擴展,只要保證新增id標識沒有使用過即可Thrift支持欄位擴展。新增欄位為required類型時,需要設置默認值Hessian支持欄位擴展Avro支持欄位擴展。注意需要為欄位設置默認值對比各個序列化框架序列化後的數據大小如下,可以看出kryo preregister(預先註冊序列化類)和Avro序列化結果都很不錯。所以,如果在序列化大小上有需求,可以選擇Kryo或Avro。下面是序列化與反序列化的時間開銷,kryo preregister和fst preregister都能提供優異的性能,其中fst pre序列化時間就最佳,而kryo pre在序列化和反序列化時間開銷上基本一致。所以,如果序列化時間是主要的考慮指標,可以選擇Kryo或FST,都能提供不錯的性能體驗。

List測試內容:ArrayList、LinkedList、Stack、CopyOnWriteArrayList、Vector。

Set測試內容:HashSet、LinkedHashSet、TreeSet、CopyOnWriteArraySet。

Map測試內容:HashMap、LinkedHashMap、TreeMap、WeakHashMap、ConcurrentHashMap、Hashtable。

Queue測試內容:PriorityQueue、ArrayBlockingQueue、LinkedBlockingQueue、ConcurrentLinkedQueue、SynchronousQueue、ArrayDeque、LinkedBlockingDeque和ConcurrentLinkedDeque。

下面根據測試總結了以上序列化框架所能支持的數據類型、語法。

由於Protobuf、Thrift是IDL定義類文件,然後使用各自的編譯器生成Java代碼。IDL沒有提供定義staic內部類、非static內部類等語法,所以這些功能無法測試。

阿里雲開發者社區

世界讀書日,來讀書吧

4月23日是第26個世界讀書日,阿里雲開發者社區推出「記錄閱讀之路,影響同行之人」活動,6位阿里技術人為同學們分享他們看過的好書,開發者藏經閣也推出了最受大家歡迎的電子書。

點擊「閱讀原文」,推薦曾經影響你的書,來一起讀書吧~

相關焦點

  • 幾種 Java 常用序列化框架的選型與對比
    本文會將業界開源的序列化框架進行對比測試,分別從通用性、易用性、可擴展性、性能和數據類型與Java語法支持五方面給出對比測試。通用性:通用性是指序列化框架是否支持跨語言、跨平臺。易用性:易用性是指序列化框架是否便於使用、調試,會影響開發效率。可擴展性:隨著業務的發展,傳輸實體可能會發生變化,但是舊實體有可能還會被使用。這時候就需要考慮所選擇的序列化框架是否具有良好的擴展性。
  • 序列化框架的選型和比對
    下邊我們來一一介紹一下現在比較常見的幾款序列化技術框架。jdk序列化jdk自身便帶有序列化的功能,Java序列化API允許我們將一個對象轉換為流,並通過網絡發送,或將其存入文件或資料庫以便未來使用,反序列化則是將對象流轉換為實際程序中使用的Java對象的過程。
  • JAVA中幾種常用的RPC框架介紹
    Java中的RPC框架比較多,各有特色,廣泛使用的有RMI、Hessian、Dubbo等。RPC還有一個特點就是能夠跨語言,本文只以JAVA語言裡的RPC為例。對於RPC有一個邏輯關係圖,以RMI為例:其他的框架結構也類似,區別在於對象的序列化方法,傳輸對象的通訊協議,以及註冊中心的管理與failover設計(利用zookeeper)。
  • Java中幾種常用的RPC框架介紹
    其他的框架結構也類似,區別在於對象的序列化方法,傳輸對象的通訊協議,以及註冊中心的管理與failover設計(利用zookeeper)。客戶端和服務端可以運行在不同的JVM中,Client只需要引入接口,接口的實現以及運行時需要的數據都在Server端,RPC的主要依賴技術是序列化、反序列化和傳輸協議,JAVA裡對應的就是對象的序列化、反序列化以及序列化後數據的傳輸。
  • Java序列化的幾種方式以及序列化的作用
    沒錯,這裡就出現了java的序列化的概念。在Java的OutputStream類下面的子類ObjectOutput-Stream類就有對應的WriteObject(Object object) 其中要求對應的object實現了java的序列化的接口。
  • Java 幾種常用 JSON 庫性能比較
    作者:熊能原文地址:www.xncoding.com/2018/01/09/java/jsons.html本篇通過JMH來測試一下Java中幾種常見的JSON解析庫的性能。目前對於Java開源的JSON類庫有很多種,下面我們取4個常用的JSON庫進行性能測試對比, 同時根據測試結果分析如果根據實際應用場景選擇最合適的JSON庫。這4個JSON類庫分別為:Gson,FastJson,Jackson,Json-lib。
  • JAVA中幾種常用JSON庫性能比較
    作者丨飛汙熊xncoding.com/2018/01/09/java/jsons.html本篇通過JMH來測試一下Java中幾種常見的JSON解析庫的性能。目前對於Java開源的JSON類庫有很多種,下面我們取4個常用的JSON庫進行性能測試對比, 同時根據測試結果分析如果根據實際應用場景選擇最合適的JSON庫。這4個JSON類庫分別為:Gson,FastJson,Jackson,Json-lib。
  • Java幾種常用JSON庫性能比較
    作者:飛汙熊xncoding.com/2018/01/09/java/jsons.html本篇通過JMH來測試一下Java
  • Java程式設計師必備:序列化全方位解析
    本文從以下幾個角度來解析序列這一塊知識點~什麼是Java序列化?為什麼需要序列化?序列化用途Java序列化常用API序列化的使用序列化底層日常開發序列化的注意點序列化常見面試題一、什麼是Java序列化?
  • 詳解JAVA序列化
    這個時候我們就需要通過固定的協議,傳輸固定的數據格式,而這個數據傳輸的協議稱之為序列化,而定義了傳輸數據行為的框架組件也稱之為序列化組件(框架)序列化有什麼意義首先我們先看看,java中的序列化,在java語言中實例對象想要序列化傳輸,需要實現Serializable 接口,只有當前接口修飾定義的類對象才可以按照指定的方式傳輸對象。
  • 序列化與反序列化
    為了提供高質量的數據服務,為了實現與上下遊各系統進行良好的對接,序列化和反序列化的選型往往是我們做系統設計的一個重要考慮因素。>第四部分分別講解了目前常見的幾種序列化協議的特性,應用場景,並對相關組件進行舉例;最後一部分,基於各種協議的特性,以及相關benchmark數據,給出了作者的技術選型建議。
  • Java常用的幾個Json庫,性能強勢對比!
    本篇通過JMH來測試一下Java中幾種常見的JSON解析庫的性能。每次都在網上看到別人說什麼某某庫性能是如何如何的好,碾壓其他的庫。
  • java反序列化的研究
    遊走於各類項目,你會發現政府和大型企業是很喜歡使用java去進行開發,同時也使用一些框架、java中間件、java庫文件去使得開發變得簡單。對於java,滲透測試過程中最常見的漏洞就是反序列化。並且一旦存在反序列化漏洞,就很容易getshell。既然反序列化如此危險,那政府企業為啥麼還要使用這個功能呢?難道是專門為黑客留一絲念想?
  • Java反序列化漏洞從入門到深入
    而在眾多漏洞中,最數反序列化漏洞的表現最『輝煌』,從15年影響WebSphere、JBoss、Jenkins、WebLogic等大型框架的Apache Commons Collections 反序列化遠程命令執行漏洞,到17年末WebLogic XML 反序列化引起的挖礦風波,反序列化漏洞一直在路上……學習本系列文章需要的Java基礎:了解Java基礎語法及結構(菜鳥教程
  • Java Web安全 || Java基礎 · Java 序列化/反序列化
    DeserializationTest.class, Object.class.getConstructor() ); // 實例化DeserializationTest對象 System.out.println(constructor.newInstance
  • 學Java必須會的20種常用類庫和API,你知道幾個?
    順便說一句,這裡不包括框架,如Spring和Hibernate因為他們非常有名,都有特定的功能。本文總結了日誌、JSON解析、單測、XML解析、字節碼處理、資料庫連接池、集合類、郵件、加密、嵌入式SQL資料庫、JDBC故障診斷以及序列化等20個方面的常用類庫。相信對你還是有些幫助的!日誌庫是很常見的,因為你在每一個項目中都需要他們。
  • 幾種常用JSON解析庫性能比較
    作者:飛汙熊xncoding.com/2018/01/09/java/jsons.html本篇通過JMH來測試一下Java中幾種常見的JSON解析庫的性能。 每次都在網上看到別人說什麼某某庫性能是如何如何的好,碾壓其他的庫。但是百聞不如一見,只有自己親手測試過的才是最值得相信的。
  • Jackson框架Java反序列化遠程代碼執行漏洞
    北京時間4月15日,Jackson框架被發現存在一個反序列化代碼執行漏洞。
  • 關於Python框架的那些事!(常用Python框架,區別,性能對比)
    無論你是大神也好小白也罷,了解幾款Python常用框架是絕對有必要的,否則真不好意思跟別人說學過Python😁😁。下面再次為大家介紹幾款Python常用框架以及它們的區別與性能對比。目前比較流行的大家常用的Python框架一般是Django、Flask、Scrapy、Cubes、Pulsar和Tornado。下面我們一起來看看這些Python框架的不同適用環境。Django:Python全能型Web框架
  • JAVA RMI反序列化知識詳解
    二、RMI簡介JAVA本身提供了一種RPC框架 RMI及Java 遠程方法調用(Java Remote Method Invocation),可以在不同的Java 虛擬機之間進行對象間的通訊,RMI是基於JRMP協議(Java Remote Message Protocol Java遠程消息交換協議)去實現的。