Kryo是一個快速有效的對象圖序列化Java庫。它的目標是快速、高效、易使用。該項目適用於對象持久化到文件或數據庫中或經過網絡傳輸。Kryo還能夠自動實現深淺的拷貝/克隆。 就是直接複製一個對象對象到另外一個對象,而不是對象轉換爲字節而後轉化爲對象。java
目前已經被用在下列項目中:
KryoNet (NIO networking)
Twitter's Scalding (Scala API for Cascading)
Twitter's Chill (Kryo serializers for Scala)
Apache Fluo (Kryo is default serialization for Fluo Recipes)
Apache Hive (query plan serialization)
Apache Spark (shuffled/cached data serialization)
DataNucleus (JDO/JPA persistence framework)
CloudPelican
Yahoo's S4 (distributed stream computing)
Storm (distributed realtime computation system, in turn used by many others)
Cascalog (Clojure/Java data processing and querying details)
memcached-session-manager (Tomcat high-availability sessions)
Mobility-RPC (RPC enabling distributed applications)
akka-kryo-serialization (Kryo serializers for Akka)
Groupon
Jive
DestroyAllHumans (controls a robot!)
kryo-serializers (additional serializers)git
Kryo序列化實例:github
Kryo kryo = new Kryo(); // ... Output output = new Output(new FileOutputStream("file.bin")); SomeClass someObject = ... kryo.writeObject(output, someObject); output.close(); // ... Input input = new Input(new FileInputStream("file.bin")); SomeClass someObject = kryo.readObject(input, SomeClass.class); input.close();
Kryo默認爲不一樣的數據類型定義了不一樣的序列化器,其具體類型以下所示:數據庫
col1 | col2 | col3 | col4 | col5 |
---|---|---|---|---|
boolean | Boolean | byte | Byte | char |
Character | short | Short | int | Integer |
long | Long | float | Float | double |
Double | byte[] | String | BigInteger | BigDecimal |
Collection | Date | Collections.emptyList | Collections.singleton | Map |
StringBuilder | TreeMap | Collections.emptyMap | Collections.emptySet | KryoSerializable |
StringBuffer | Class | Collections.singletonList | Collections.singletonMap | Currency |
Calendar | TimeZone | Enum | EnumSet |
Kryo類在構造參數中會爲上述表中的類型初始化對應的序列化類。apache
其它類會使用默認序列化器FieldSerializer,固然你也能夠經過下面的代碼更改默認序列化器:api
Kryo kryo = new Kryo(); kryo.setDefaultSerializer(AnotherGenericSerializer.class);
也能夠爲每一個類指定序列化類,以下網絡
Kryo kryo = new Kryo(); kryo.register(SomeClass.class, new SomeSerializer()); kryo.register(AnotherClass.class, new AnotherSerializer());
1.下面經過如下Kryo4.0源代碼看一下
Kryo類的構造函數爲:session
public Kryo (ClassResolver classResolver, ReferenceResolver referenceResolver, StreamFactory streamFactory) { if (classResolver == null) throw new IllegalArgumentException("classResolver cannot be null."); this.classResolver = classResolver; classResolver.setKryo(this); this.streamFactory = streamFactory; streamFactory.setKryo(this); this.referenceResolver = referenceResolver; if (referenceResolver != null) { referenceResolver.setKryo(this); references = true; } //private final ArrayList<DefaultSerializerEntry> defaultSerializers = new ArrayList(33);用一個大小爲33的Entry來存放類及序列化器 addDefaultSerializer(byte[].class, ByteArraySerializer.class); addDefaultSerializer(char[].class, CharArraySerializer.class); addDefaultSerializer(short[].class, ShortArraySerializer.class); addDefaultSerializer(int[].class, IntArraySerializer.class); addDefaultSerializer(long[].class, LongArraySerializer.class); addDefaultSerializer(float[].class, FloatArraySerializer.class); addDefaultSerializer(double[].class, DoubleArraySerializer.class); addDefaultSerializer(boolean[].class, BooleanArraySerializer.class); addDefaultSerializer(String[].class, StringArraySerializer.class); addDefaultSerializer(Object[].class, ObjectArraySerializer.class); addDefaultSerializer(KryoSerializable.class, KryoSerializableSerializer.class); addDefaultSerializer(BigInteger.class, BigIntegerSerializer.class); addDefaultSerializer(BigDecimal.class, BigDecimalSerializer.class); addDefaultSerializer(Class.class, ClassSerializer.class); addDefaultSerializer(Date.class, DateSerializer.class); addDefaultSerializer(Enum.class, EnumSerializer.class); addDefaultSerializer(EnumSet.class, EnumSetSerializer.class); addDefaultSerializer(Currency.class, CurrencySerializer.class); addDefaultSerializer(StringBuffer.class, StringBufferSerializer.class); addDefaultSerializer(StringBuilder.class, StringBuilderSerializer.class); addDefaultSerializer(Collections.EMPTY_LIST.getClass(), CollectionsEmptyListSerializer.class); addDefaultSerializer(Collections.EMPTY_MAP.getClass(), CollectionsEmptyMapSerializer.class); addDefaultSerializer(Collections.EMPTY_SET.getClass(), CollectionsEmptySetSerializer.class); addDefaultSerializer(Collections.singletonList(null).getClass(), CollectionsSingletonListSerializer.class); addDefaultSerializer(Collections.singletonMap(null, null).getClass(), CollectionsSingletonMapSerializer.class); addDefaultSerializer(Collections.singleton(null).getClass(), CollectionsSingletonSetSerializer.class); addDefaultSerializer(TreeSet.class, TreeSetSerializer.class); addDefaultSerializer(Collection.class, CollectionSerializer.class); addDefaultSerializer(TreeMap.class, TreeMapSerializer.class); addDefaultSerializer(Map.class, MapSerializer.class); addDefaultSerializer(TimeZone.class, TimeZoneSerializer.class); addDefaultSerializer(Calendar.class, CalendarSerializer.class); addDefaultSerializer(Locale.class, LocaleSerializer.class); addDefaultSerializer(Charset.class, CharsetSerializer.class); addDefaultSerializer(URL.class, URLSerializer.class); OptionalSerializers.addDefaultSerializers(this); TimeSerializers.addDefaultSerializers(this); lowPriorityDefaultSerializerCount = defaultSerializers.size(); // Primitives and string. Primitive wrappers automatically use the same registration as primitives. register(int.class, new IntSerializer()); register(String.class, new StringSerializer()); register(float.class, new FloatSerializer()); register(boolean.class, new BooleanSerializer()); register(byte.class, new ByteSerializer()); register(char.class, new CharSerializer()); register(short.class, new ShortSerializer()); register(long.class, new LongSerializer()); register(double.class, new DoubleSerializer()); register(void.class, new VoidSerializer()); }
2.爲何在使用一個類以前先要將Kryo註冊一下?
在序列化時寫一個類名是低效的,因此用一個ID來替代類名,只須要使用前完成註冊便可,代碼以下:app
//用先一個可用的整型ID來註冊該類,若是類已經被註冊,那麼就返回以前的註冊信息類 public Registration register (Class type) { Registration registration = classResolver.getRegistration(type); if (registration != null) return registration; return register(type, getDefaultSerializer(type)); } //和上面的基本同樣,只不過是本身定義ID public Registration register (Class type, int id) { Registration registration = classResolver.getRegistration(type); if (registration != null) return registration; return register(type, getDefaultSerializer(type), id); }
官方文檔中有一段話:ide
Using Unsafe-based IO may result in a quite significant performance boost (sometimes up-to an order of magnitude), depending on your application. In particular, it helps a lot when serializing large primitive arrays as part of your object graphs.
下面是答案:
Unsafe-based IO uses methods from sun.misc.Unsafe for reading and writing from/to memory. Many of those methods map almost 1:1 to processor instructions. Moreover, reading/writing of arrays of native types is executed in bulk instead of doing it element-by-element as it is usually done by Kryo. Together, these features often provide a significant performance boost.