序列化和反序列化做爲Java裏一個較爲基礎的知識點,你們內心也有那麼幾句要說的,但我相信不少小夥伴掌握的也就是那麼幾句而已,若是再深究問一下Java如何實現序列化和反序列化的,就可能不知所措了!遙記當年也被問了這一個問題,自信滿滿的說了一大堆,什麼是序列化、什麼是反序列化、什麼場景的時候纔會用到等,而後面試官說:那你能說一下序列化和反序列化底層是如何實現的嗎?一臉懵逼,而後回家等通知!
java
一、什麼是序列化和反序列化git
(1)Java序列化是指把Java對象轉換爲字節序列的過程,而Java反序列化是指把字節序列恢復爲Java對象的過程;面試
(2)序列化:對象序列化的最主要的用處就是在傳遞和保存對象的時候,保證對象的完整性和可傳遞性。序列化是把對象轉換成有序字節流,以便在網絡上傳輸或者保存在本地文件中。序列化後的字節流保存了Java對象的狀態以及相關的描述信息。序列化機制的核心做用就是對象狀態的保存與重建。算法
(3)反序列化:客戶端從文件中或網絡上得到序列化後的對象字節流後,根據字節流中所保存的對象狀態及描述信息,經過反序列化重建對象。數據庫
(4)本質上講,序列化就是把實體對象狀態按照必定的格式寫入到有序字節流,反序列化就是從有序字節流重建對象,恢復對象狀態。apache
二、爲何須要序列化與反序列化網絡
咱們知道,當兩個進程進行遠程通訊時,能夠相互發送各類類型的數據,包括文本、圖片、音頻、視頻等, 而這些數據都會以二進制序列的形式在網絡上傳送。app
那麼當兩個Java進程進行通訊時,可否實現進程間的對象傳送呢?答案是能夠的!如何作到呢?這就須要Java序列化與反序列化了!框架
換句話說,一方面,發送方須要把這個Java對象轉換爲字節序列,而後在網絡上傳送;另外一方面,接收方須要從字節序列中恢復出Java對象。koa
當咱們明晰了爲何須要Java序列化和反序列化後,咱們很天然地會想Java序列化的好處。其好處一是實現了數據的持久化,經過序列化能夠把數據永久地保存到硬盤上(一般存放在文件裏),二是,利用序列化實現遠程通訊,即在網絡上傳送對象的字節序列。
總的來講能夠歸結爲如下幾點:
(1)永久性保存對象,保存對象的字節序列到本地文件或者數據庫中;
(2)經過序列化以字節流的形式使對象在網絡中進行傳遞和接收;
(3)經過序列化在進程間傳遞對象;
三、序列化算法通常會按步驟作以下事情:
(1)將對象實例相關的類元數據輸出。
(2)遞歸地輸出類的超類描述直到再也不有超類。
(3)類元數據完了之後,開始從最頂層的超類開始輸出對象實例的實際數據值。
(4)從上至下遞歸輸出實例的數據
四、各類 Java 的序列化庫的性能比較測試結果
圖片來源於網絡,能夠說明對原生序列化來說,其餘三方框架提供的序列化協議要快不少,因此咱們作RPC技術選型的時候,序列化協議這塊必定要摒棄原生序列化,去選擇一款本身熟悉的序列化協議來傳輸IO流。下面選擇作一個thrift序列化和原生序列化的對比結果。
原生序列化user類
package util.dto; import java.io.Serializable; public class User implements Serializable { private String name; private Integer integer; private String address; public User(String name, Integer integer, String address) { this.name = name; this.integer = integer; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getInteger() { return integer; } public void setInteger(Integer integer) { this.integer = integer; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
原生序列化工具類
1 package util; 2 3 import java.io.*; 4 import java.util.Arrays; 5 6 public class SerializeUtil { 7 8 /** 序列化對象 9 * @throws IOException */ 10 public static byte[] serializeObject(Object object) throws IOException { 11 ByteArrayOutputStream saos = new ByteArrayOutputStream (); 12 ObjectOutputStream oos = new ObjectOutputStream(saos); 13 oos.writeObject(object); 14 oos.flush(); 15 return saos.toByteArray(); 16 } 17 18 /** 反序列化對象 19 * @throws IOException 20 * @throws ClassNotFoundException */ 21 public static Object deserializeObject(byte[] buf) throws IOException, ClassNotFoundException{ 22 Object object=null; 23 ByteArrayInputStream sais=new ByteArrayInputStream(buf); 24 ObjectInputStream ois = new ObjectInputStream(sais); 25 object = ois.readObject(); 26 return object; 27 } 28 }
由thrift腳本生成的User類
1 /** 2 * Autogenerated by Thrift Compiler (0.8.0) 3 * 4 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 * @generated 6 */ 7 package util.dtothrift; 8 9 import org.apache.thrift.scheme.IScheme; 10 import org.apache.thrift.scheme.SchemeFactory; 11 import org.apache.thrift.scheme.StandardScheme; 12 13 import org.apache.thrift.scheme.TupleScheme; 14 import org.apache.thrift.protocol.TTupleProtocol; 15 import java.util.List; 16 import java.util.ArrayList; 17 import java.util.Map; 18 import java.util.HashMap; 19 import java.util.EnumMap; 20 import java.util.Set; 21 import java.util.HashSet; 22 import java.util.EnumSet; 23 import java.util.Collections; 24 import java.util.BitSet; 25 import java.nio.ByteBuffer; 26 import java.util.Arrays; 27 import org.slf4j.Logger; 28 import org.slf4j.LoggerFactory; 29 30 public class User implements org.apache.thrift.TBase<User, User._Fields>, java.io.Serializable, Cloneable { 31 private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("User"); 32 33 private static final org.apache.thrift.protocol.TField STR_FIELD_DESC = new org.apache.thrift.protocol.TField("str", org.apache.thrift.protocol.TType.STRING, (short)1); 34 private static final org.apache.thrift.protocol.TField AGE_FIELD_DESC = new org.apache.thrift.protocol.TField("age", org.apache.thrift.protocol.TType.I32, (short)2); 35 private static final org.apache.thrift.protocol.TField ADDRESS_FIELD_DESC = new org.apache.thrift.protocol.TField("address", org.apache.thrift.protocol.TType.STRING, (short)3); 36 37 private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>(); 38 static { 39 schemes.put(StandardScheme.class, new UserStandardSchemeFactory()); 40 schemes.put(TupleScheme.class, new UserTupleSchemeFactory()); 41 } 42 43 public String str; // required 44 public int age; // required 45 public String address; // required 46 47 /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ 48 public enum _Fields implements org.apache.thrift.TFieldIdEnum { 49 STR((short)1, "str"), 50 AGE((short)2, "age"), 51 ADDRESS((short)3, "address"); 52 53 private static final Map<String, _Fields> byName = new HashMap<String, _Fields>(); 54 55 static { 56 for (_Fields field : EnumSet.allOf(_Fields.class)) { 57 byName.put(field.getFieldName(), field); 58 } 59 } 60 61 /** 62 * Find the _Fields constant that matches fieldId, or null if its not found. 63 */ 64 public static _Fields findByThriftId(int fieldId) { 65 switch(fieldId) { 66 case 1: // STR 67 return STR; 68 case 2: // AGE 69 return AGE; 70 case 3: // ADDRESS 71 return ADDRESS; 72 default: 73 return null; 74 } 75 } 76 77 /** 78 * Find the _Fields constant that matches fieldId, throwing an exception 79 * if it is not found. 80 */ 81 public static _Fields findByThriftIdOrThrow(int fieldId) { 82 _Fields fields = findByThriftId(fieldId); 83 if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); 84 return fields; 85 } 86 87 /** 88 * Find the _Fields constant that matches name, or null if its not found. 89 */ 90 public static _Fields findByName(String name) { 91 return byName.get(name); 92 } 93 94 private final short _thriftId; 95 private final String _fieldName; 96 97 _Fields(short thriftId, String fieldName) { 98 _thriftId = thriftId; 99 _fieldName = fieldName; 100 } 101 102 public short getThriftFieldId() { 103 return _thriftId; 104 } 105 106 public String getFieldName() { 107 return _fieldName; 108 } 109 } 110 111 // isset id assignments 112 private static final int __AGE_ISSET_ID = 0; 113 private BitSet __isset_bit_vector = new BitSet(1); 114 public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; 115 static { 116 Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); 117 tmpMap.put(_Fields.STR, new org.apache.thrift.meta_data.FieldMetaData("str", org.apache.thrift.TFieldRequirementType.DEFAULT, 118 new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); 119 tmpMap.put(_Fields.AGE, new org.apache.thrift.meta_data.FieldMetaData("age", org.apache.thrift.TFieldRequirementType.DEFAULT, 120 new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32))); 121 tmpMap.put(_Fields.ADDRESS, new org.apache.thrift.meta_data.FieldMetaData("address", org.apache.thrift.TFieldRequirementType.DEFAULT, 122 new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); 123 metaDataMap = Collections.unmodifiableMap(tmpMap); 124 org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(User.class, metaDataMap); 125 } 126 127 public User() { 128 } 129 130 public User( 131 String str, 132 int age, 133 String address) 134 { 135 this(); 136 this.str = str; 137 this.age = age; 138 setAgeIsSet(true); 139 this.address = address; 140 } 141 142 /** 143 * Performs a deep copy on <i>other</i>. 144 */ 145 public User(User other) { 146 __isset_bit_vector.clear(); 147 __isset_bit_vector.or(other.__isset_bit_vector); 148 if (other.isSetStr()) { 149 this.str = other.str; 150 } 151 this.age = other.age; 152 if (other.isSetAddress()) { 153 this.address = other.address; 154 } 155 } 156 157 public User deepCopy() { 158 return new User(this); 159 } 160 161 @Override 162 public void clear() { 163 this.str = null; 164 setAgeIsSet(false); 165 this.age = 0; 166 this.address = null; 167 } 168 169 public String getStr() { 170 return this.str; 171 } 172 173 public User setStr(String str) { 174 this.str = str; 175 return this; 176 } 177 178 public void unsetStr() { 179 this.str = null; 180 } 181 182 /** Returns true if field str is set (has been assigned a value) and false otherwise */ 183 public boolean isSetStr() { 184 return this.str != null; 185 } 186 187 public void setStrIsSet(boolean value) { 188 if (!value) { 189 this.str = null; 190 } 191 } 192 193 public int getAge() { 194 return this.age; 195 } 196 197 public User setAge(int age) { 198 this.age = age; 199 setAgeIsSet(true); 200 return this; 201 } 202 203 public void unsetAge() { 204 __isset_bit_vector.clear(__AGE_ISSET_ID); 205 } 206 207 /** Returns true if field age is set (has been assigned a value) and false otherwise */ 208 public boolean isSetAge() { 209 return __isset_bit_vector.get(__AGE_ISSET_ID); 210 } 211 212 public void setAgeIsSet(boolean value) { 213 __isset_bit_vector.set(__AGE_ISSET_ID, value); 214 } 215 216 public String getAddress() { 217 return this.address; 218 } 219 220 public User setAddress(String address) { 221 this.address = address; 222 return this; 223 } 224 225 public void unsetAddress() { 226 this.address = null; 227 } 228 229 /** Returns true if field address is set (has been assigned a value) and false otherwise */ 230 public boolean isSetAddress() { 231 return this.address != null; 232 } 233 234 public void setAddressIsSet(boolean value) { 235 if (!value) { 236 this.address = null; 237 } 238 } 239 240 public void setFieldValue(_Fields field, Object value) { 241 switch (field) { 242 case STR: 243 if (value == null) { 244 unsetStr(); 245 } else { 246 setStr((String)value); 247 } 248 break; 249 250 case AGE: 251 if (value == null) { 252 unsetAge(); 253 } else { 254 setAge((Integer)value); 255 } 256 break; 257 258 case ADDRESS: 259 if (value == null) { 260 unsetAddress(); 261 } else { 262 setAddress((String)value); 263 } 264 break; 265 266 } 267 } 268 269 public Object getFieldValue(_Fields field) { 270 switch (field) { 271 case STR: 272 return getStr(); 273 274 case AGE: 275 return Integer.valueOf(getAge()); 276 277 case ADDRESS: 278 return getAddress(); 279 280 } 281 throw new IllegalStateException(); 282 } 283 284 /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ 285 public boolean isSet(_Fields field) { 286 if (field == null) { 287 throw new IllegalArgumentException(); 288 } 289 290 switch (field) { 291 case STR: 292 return isSetStr(); 293 case AGE: 294 return isSetAge(); 295 case ADDRESS: 296 return isSetAddress(); 297 } 298 throw new IllegalStateException(); 299 } 300 301 @Override 302 public boolean equals(Object that) { 303 if (that == null) 304 return false; 305 if (that instanceof User) 306 return this.equals((User)that); 307 return false; 308 } 309 310 public boolean equals(User that) { 311 if (that == null) 312 return false; 313 314 boolean this_present_str = true && this.isSetStr(); 315 boolean that_present_str = true && that.isSetStr(); 316 if (this_present_str || that_present_str) { 317 if (!(this_present_str && that_present_str)) 318 return false; 319 if (!this.str.equals(that.str)) 320 return false; 321 } 322 323 boolean this_present_age = true; 324 boolean that_present_age = true; 325 if (this_present_age || that_present_age) { 326 if (!(this_present_age && that_present_age)) 327 return false; 328 if (this.age != that.age) 329 return false; 330 } 331 332 boolean this_present_address = true && this.isSetAddress(); 333 boolean that_present_address = true && that.isSetAddress(); 334 if (this_present_address || that_present_address) { 335 if (!(this_present_address && that_present_address)) 336 return false; 337 if (!this.address.equals(that.address)) 338 return false; 339 } 340 341 return true; 342 } 343 344 @Override 345 public int hashCode() { 346 return 0; 347 } 348 349 public int compareTo(User other) { 350 if (!getClass().equals(other.getClass())) { 351 return getClass().getName().compareTo(other.getClass().getName()); 352 } 353 354 int lastComparison = 0; 355 User typedOther = (User)other; 356 357 lastComparison = Boolean.valueOf(isSetStr()).compareTo(typedOther.isSetStr()); 358 if (lastComparison != 0) { 359 return lastComparison; 360 } 361 if (isSetStr()) { 362 lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.str, typedOther.str); 363 if (lastComparison != 0) { 364 return lastComparison; 365 } 366 } 367 lastComparison = Boolean.valueOf(isSetAge()).compareTo(typedOther.isSetAge()); 368 if (lastComparison != 0) { 369 return lastComparison; 370 } 371 if (isSetAge()) { 372 lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.age, typedOther.age); 373 if (lastComparison != 0) { 374 return lastComparison; 375 } 376 } 377 lastComparison = Boolean.valueOf(isSetAddress()).compareTo(typedOther.isSetAddress()); 378 if (lastComparison != 0) { 379 return lastComparison; 380 } 381 if (isSetAddress()) { 382 lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.address, typedOther.address); 383 if (lastComparison != 0) { 384 return lastComparison; 385 } 386 } 387 return 0; 388 } 389 390 public _Fields fieldForId(int fieldId) { 391 return _Fields.findByThriftId(fieldId); 392 } 393 394 public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { 395 schemes.get(iprot.getScheme()).getScheme().read(iprot, this); 396 } 397 398 public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { 399 schemes.get(oprot.getScheme()).getScheme().write(oprot, this); 400 } 401 402 @Override 403 public String toString() { 404 StringBuilder sb = new StringBuilder("User("); 405 boolean first = true; 406 407 sb.append("str:"); 408 if (this.str == null) { 409 sb.append("null"); 410 } else { 411 sb.append(this.str); 412 } 413 first = false; 414 if (!first) sb.append(", "); 415 sb.append("age:"); 416 sb.append(this.age); 417 first = false; 418 if (!first) sb.append(", "); 419 sb.append("address:"); 420 if (this.address == null) { 421 sb.append("null"); 422 } else { 423 sb.append(this.address); 424 } 425 first = false; 426 sb.append(")"); 427 return sb.toString(); 428 } 429 430 public void validate() throws org.apache.thrift.TException { 431 // check for required fields 432 } 433 434 private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { 435 try { 436 write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); 437 } catch (org.apache.thrift.TException te) { 438 throw new java.io.IOException(te); 439 } 440 } 441 442 private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { 443 try { 444 // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. 445 __isset_bit_vector = new BitSet(1); 446 read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); 447 } catch (org.apache.thrift.TException te) { 448 throw new java.io.IOException(te); 449 } 450 } 451 452 private static class UserStandardSchemeFactory implements SchemeFactory { 453 public UserStandardScheme getScheme() { 454 return new UserStandardScheme(); 455 } 456 } 457 458 private static class UserStandardScheme extends StandardScheme<User> { 459 460 public void read(org.apache.thrift.protocol.TProtocol iprot, User struct) throws org.apache.thrift.TException { 461 org.apache.thrift.protocol.TField schemeField; 462 iprot.readStructBegin(); 463 while (true) 464 { 465 schemeField = iprot.readFieldBegin(); 466 if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 467 break; 468 } 469 switch (schemeField.id) { 470 case 1: // STR 471 if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { 472 struct.str = iprot.readString(); 473 struct.setStrIsSet(true); 474 } else { 475 org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 476 } 477 break; 478 case 2: // AGE 479 if (schemeField.type == org.apache.thrift.protocol.TType.I32) { 480 struct.age = iprot.readI32(); 481 struct.setAgeIsSet(true); 482 } else { 483 org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 484 } 485 break; 486 case 3: // ADDRESS 487 if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { 488 struct.address = iprot.readString(); 489 struct.setAddressIsSet(true); 490 } else { 491 org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 492 } 493 break; 494 default: 495 org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 496 } 497 iprot.readFieldEnd(); 498 } 499 iprot.readStructEnd(); 500 501 // check for required fields of primitive type, which can't be checked in the validate method 502 struct.validate(); 503 } 504 505 public void write(org.apache.thrift.protocol.TProtocol oprot, User struct) throws org.apache.thrift.TException { 506 struct.validate(); 507 508 oprot.writeStructBegin(STRUCT_DESC); 509 if (struct.str != null) { 510 oprot.writeFieldBegin(STR_FIELD_DESC); 511 oprot.writeString(struct.str); 512 oprot.writeFieldEnd(); 513 } 514 oprot.writeFieldBegin(AGE_FIELD_DESC); 515 oprot.writeI32(struct.age); 516 oprot.writeFieldEnd(); 517 if (struct.address != null) { 518 oprot.writeFieldBegin(ADDRESS_FIELD_DESC); 519 oprot.writeString(struct.address); 520 oprot.writeFieldEnd(); 521 } 522 oprot.writeFieldStop(); 523 oprot.writeStructEnd(); 524 } 525 526 } 527 528 private static class UserTupleSchemeFactory implements SchemeFactory { 529 public UserTupleScheme getScheme() { 530 return new UserTupleScheme(); 531 } 532 } 533 534 private static class UserTupleScheme extends TupleScheme<User> { 535 536 @Override 537 public void write(org.apache.thrift.protocol.TProtocol prot, User struct) throws org.apache.thrift.TException { 538 TTupleProtocol oprot = (TTupleProtocol) prot; 539 BitSet optionals = new BitSet(); 540 if (struct.isSetStr()) { 541 optionals.set(0); 542 } 543 if (struct.isSetAge()) { 544 optionals.set(1); 545 } 546 if (struct.isSetAddress()) { 547 optionals.set(2); 548 } 549 oprot.writeBitSet(optionals, 3); 550 if (struct.isSetStr()) { 551 oprot.writeString(struct.str); 552 } 553 if (struct.isSetAge()) { 554 oprot.writeI32(struct.age); 555 } 556 if (struct.isSetAddress()) { 557 oprot.writeString(struct.address); 558 } 559 } 560 561 @Override 562 public void read(org.apache.thrift.protocol.TProtocol prot, User struct) throws org.apache.thrift.TException { 563 TTupleProtocol iprot = (TTupleProtocol) prot; 564 BitSet incoming = iprot.readBitSet(3); 565 if (incoming.get(0)) { 566 struct.str = iprot.readString(); 567 struct.setStrIsSet(true); 568 } 569 if (incoming.get(1)) { 570 struct.age = iprot.readI32(); 571 struct.setAgeIsSet(true); 572 } 573 if (incoming.get(2)) { 574 struct.address = iprot.readString(); 575 struct.setAddressIsSet(true); 576 } 577 } 578 } 579 580 }
測試類
1 package util; 2 3 import org.apache.thrift.TException; 4 import org.apache.thrift.protocol.TBinaryProtocol; 5 import org.apache.thrift.transport.TIOStreamTransport; 6 import org.apache.thrift.transport.TSocket; 7 import org.apache.thrift.transport.TTransport; 8 import org.slf4j.Logger; 9 import org.slf4j.LoggerFactory; 10 import util.dto.User; 11 12 import java.io.ByteArrayInputStream; 13 import java.io.ByteArrayOutputStream; 14 import java.io.IOException; 15 import java.util.Arrays; 16 17 public class SerializeTest { 18 19 private final static Logger logger = LoggerFactory.getLogger ( SerializeTest.class ); 20 21 public static void main(String[] args) throws IOException, ClassNotFoundException, TException { 22 23 long a = System.currentTimeMillis (); 24 for (int i = 0; i < 100000; i++) { 25 User user = new User("姓名"+i,i,"北京市海淀區中關村大廈"+i); 26 byte[] b = SerializeUtil.serializeObject ( user ); 27 //System.out.println (Arrays.toString ( b )); 28 User user1 = (User) SerializeUtil.deserializeObject ( b ); 29 } 30 System.out.println (System.currentTimeMillis ()-a); 31 32 long b = System.currentTimeMillis (); 33 34 for (int i = 0; i < 100000; i++) { 35 util.dtothrift.User user = new util.dtothrift.User("姓名"+i,i,"北京市海淀區中關村大廈"+i); 36 ByteArrayOutputStream out = new ByteArrayOutputStream(); 37 TTransport transport = new TIOStreamTransport (out); 38 TBinaryProtocol tp = new TBinaryProtocol(transport); 39 try { 40 user.write(tp); 41 } catch (TException e) { 42 e.printStackTrace(); 43 } 44 byte[] bytes = out.toByteArray(); 45 //System.out.println ( Arrays.toString ( bytes )); 46 util.dtothrift.User user1 = new util.dtothrift.User(); 47 48 ByteArrayInputStream bis = new ByteArrayInputStream ( bytes); 49 TTransport transport1 = new TIOStreamTransport(bis); 50 TBinaryProtocol tp1 = new TBinaryProtocol(transport1); 51 user1.read (tp1); 52 } 53 System.out.println (System.currentTimeMillis ()-b); 54 } 55 56 }
10萬次序列化和反序列化的結果對比
由上圖能夠看出,採用facebook的序列化協議要比原生jdk序列化協議在10萬次序列化和反序列化操做中的時間快不少,而且thrift沒有原生序列化的那麼多的要求,咱們來看看原生序列化和thrift序列化的輸入結果都是什麼,打開 System.out.println ( Arrays.toString ( bytes ))代碼後
jdk 輸出流
[-84, -19, 0, 5, 115, 114, 0, 13, 117, 116, 105, 108, 46, 100, 116, 111, 46, 85, 115, 101, 114, -45, 124, 21, -36, 14, -39, -44, 35, 2, 0, 3, 76, 0, 7, 97, 100, 100, 114, 101, 115, 115, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 76, 0, 7, 105, 110, 116, 101, 103, 101, 114, 116, 0, 19, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 73, 110, 116, 101, 103, 101, 114, 59, 76, 0, 4, 110, 97, 109, 101, 113, 0, 126, 0, 1, 120, 112, 116, 0, 34, -27, -116, -105, -28, -70, -84, -27, -72, -126, -26, -75, -73, -26, -73, -128, -27, -116, -70, -28, -72, -83, -27, -123, -77, -26, -99, -111, -27, -92, -89, -27, -114, -90, 48, 115, 114, 0, 17, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 73, 110, 116, 101, 103, 101, 114, 18, -30, -96, -92, -9, -127, -121, 56, 2, 0, 1, 73, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, 0, 0, 0, 116, 0, 7, -27, -89, -109, -27, -112, -115, 48]
thrift輸出流
[11, 0, 1, 0, 0, 0, 7, -27, -89, -109, -27, -112, -115, 48, 8, 0, 2, 0, 0, 0, 0, 11, 0, 3, 0, 0, 0, 34, -27, -116, -105, -28, -70, -84, -27, -72, -126, -26, -75, -73, -26, -73, -128, -27, -116, -70, -28, -72, -83, -27, -123, -77, -26, -99, -111, -27, -92, -89, -27, -114, -90, 48, 0]
由此能夠看出jdk的輸出流比thrift的輸出流多不少,由於jdk原生序列化對方法棧信息,類信息等作了詳細的記錄,其實這些信息對於RPC來講不是傳輸必要參數,因此精簡序列化IO流大小在傳輸中十分關鍵
本章對序列化進行了簡單的概述,你們能夠針對個人上面代碼進行測試。
高級java交流羣:825199617
歡迎熱愛源碼志同道合的朋友加入。
koalas rpc源碼地址https://gitee.com/a1234567891/koalas-rpc