Kryo序列化与反序列化两种方式

1、第一种是序列化对象到byte[],具体代码示例如下:

1.1 要序列化的对象类Simple.java:

package kryoserializabletest;

import java.io.Serializable;
import java.util.Map;

/**
 * Created by 0262000099 on 2018/9/6.
 */
public class Simple implements Serializable{
  private static final long serialVersionUID = -4914434736682797743L;
  private String name;
  private int age;
  private Map map;

  public Simple(){

  }
  public Simple(String name, int age, Map map){
    this.name = name;
    this.age = age;
    this.map = map;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public Map getMap() {
    return map;
  }

  public void setMap(Map map) {
    this.map = map;
  }
}

1.2 测试类KryoSerializableTest.java:

package kryoserializabletest;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.objenesis.strategy.StdInstantiatorStrategy;



import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by 0262000099 on 2018/9/7.
 */
public class KryoSerializableTest {
  public static byte[] serializeObject(Simple simple) throws IOException {
    Kryo kryo = new Kryo();
    kryo.setReferences(false);
    kryo.setRegistrationRequired(false);
    kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
    kryo.register(Simple.class);
    byte[] bytes;

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    Output output = new Output(byteArrayOutputStream, 100000000);
    Map map = new HashMap();
    for (int i = 0; i < 1000000; i++) {
      map.put("zhang0", i);
      map.put("zhang1", i);
      kryo.writeObject(output, new Simple("zhang"+i,(i+1),map));
    }
//    kryo.writeObject(output, simple);
//    错误用法:bytes = byteArrayOutputStream.toByteArray();
//    注意是output.toBytes(),而不是byteArrayOutputStream.toByteArray(),这里是kryo和java原生序列化框架的区别
    bytes = output.toBytes();
    output.close();
    byteArrayOutputStream.close();
    return bytes;
  }

  public static Simple deserializeObject(byte[] bytes){
    Kryo kryo = new Kryo();
    kryo.setReferences(false);
    kryo.setRegistrationRequired(false);
    kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());

    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
    Input input = null;
    input = new Input(byteArrayInputStream);
    Simple simple = null;
    simple = kryo.readObject(input, Simple.class);

    input.close();
    return simple;
  }

  public static void main (String[] args) throws IOException {

    Simple simple = new Simple();
    Map map = new HashMap();
    byte[] bytes = new byte[0];
    long start =  System.currentTimeMillis();
//    for (int i = 0; i < 100; i++) {
//      map.put("nht" + i, i);
//      simple.setName("nht" + i);
//      simple.setAge(i + 1);
//      simple.setMap(map);
//      bytes = serializeObject(simple);
//    }
    bytes = serializeObject(simple);
//    System.out.println("序列化前的对象:" + simple);
    System.out.println("序列化后的字节数组是:" + bytes);
    System.out.println("kryo序列化时间:" + (System.currentTimeMillis() - start) + " ms" );
    Simple simpleDe;
    start =  System.currentTimeMillis();
    simpleDe = deserializeObject(bytes);
    System.out.println("kryo反序列化时间:" + (System.currentTimeMillis() - start) + " ms");
//    System.out.println("反序列化后的对象:" + "\n" + "name:" + simpleDe.getName() + "\n" + "age:" + simpleDe.getAge()
//            + "\n" + "map:" + simpleDe.getMap());
  }
}

2、第一种是序列化对象到ByteBuffer,具体代码示例如下:

2.1 要序列化的对象类Simple.java:

package kryoserializabletest;

import java.io.Serializable;
import java.util.Map;

/**
 * Created by 0262000099 on 2018/9/6.
 */
public class Simple implements Serializable{
  private static final long serialVersionUID = -4914434736682797743L;
  private String name;
  private int age;
  private Map map;

  public Simple(){

  }
  public Simple(String name, int age, Map map){
    this.name = name;
    this.age = age;
    this.map = map;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public Map getMap() {
    return map;
  }

  public void setMap(Map map) {
    this.map = map;
  }
}

2.2 测试类KryoSerializableToByteBufferTest.java:

package kryoserializabletest;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.ByteBufferInputStream;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.objenesis.strategy.StdInstantiatorStrategy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

/**
* @Description    KryoSerializableToByteBufferTest Descripition {序列化对象到ByteBuffer}
* @Author         0262000099 Hengtai Nie
* @CreateDate     2018/9/7 15:21
*/
public class KryoSerializableToByteBufferTest {

//  将对象序列化到ByteBuffer
  public static ByteBuffer serializeObject(Simple simple) throws IOException {
    Kryo kryo = new Kryo();
    kryo.setReferences(false);
    kryo.setRegistrationRequired(false);
    kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
    kryo.register(Simple.class);
    byte[] bytes;

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//    注意new output的时候设置buffersize的大小,如果buffersize太小会报出unregistered class ID 的错误
    Output output = new Output(byteArrayOutputStream, 100000000);
    Map map = new HashMap();
    for (int i = 0; i < 1000000; i++) {
      map.put("zhang0", i);
      map.put("zhang1", i);
      kryo.writeObject(output, new Simple("zhang"+i,(i+1),map));
    }
//    kryo.writeObject(output, simple);
//    错误用法:bytes = byteArrayOutputStream.toByteArray();
//    注意是output.toBytes(),而不是byteArrayOutputStream.toByteArray(),这里是kryo和java原生序列化框架的区别
    bytes = output.toBytes();

//    将对象序列化到bytebuffer
    ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
    output.close();
    byteArrayOutputStream.close();
    return byteBuffer;
  }


  public static Simple deserializeObject(ByteBuffer byteBuffer){
    Kryo kryo = new Kryo();
    kryo.setReferences(false);
    kryo.setRegistrationRequired(false);
    kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());

    ByteBufferInputStream byteArrayInputStream = new ByteBufferInputStream(byteBuffer);
    Input input = null;
    input = new Input(byteArrayInputStream);
    Simple simple;
    simple = kryo.readObject(input, Simple.class);
    input.close();
    return simple;
  }

  public static void main (String[] args) throws IOException {

    Simple simple = new Simple();
    Map map = new HashMap();
    ByteBuffer byteBuffer = null;
    long start = System.currentTimeMillis();
//    for (int i = 0; i < 100; i++) {
//      map.put("nht" + i, i);
//      simple.setName("nht" + i);
//      simple.setAge(i + 1);
//      simple.setMap(map);
//      byteBuffer = serializeObject(simple);
//    }
    byteBuffer = serializeObject(simple);
    System.out.println("序列化时间是:" + (System.currentTimeMillis() - start) + " ms");
    System.out.println("序列化后的字节数组:" + byteBuffer);

    Simple simpleDe;
    long startDe = System.currentTimeMillis();
    simpleDe = deserializeObject(byteBuffer);
    System.out.println("反序列化时间是:" + (System.currentTimeMillis() - startDe) + "ms");
//    System.out.println("反序列化后的对象:" + "\n" + "name:" + simpleDe.getName() + "\n" + "age:" + simpleDe.getAge()
//            + "\n" + "map:" + simpleDe.getMap());
  }
}

3、遇到的问题

问题1、 Exception in thread “main” com.esotericsoftware.kryo.KryoException: Buffer underflow.

解决:使用Kryo序列化时,相比于使用java原生的序列化框架会多生成一个Output对象,因此需要将该对象转成字节数组,而不是将ByteArrayOutputStream对象转成字节数组;

Output output = new Output(byteArrayOutputStream, 100000000);
//
......
//    错误用法:bytes = byteArrayOutputStream.toByteArray();
//    注意是output.toBytes(),而不是byteArrayOutputStream.toByteArray(),这里是kryo和java原生序列化框架的区别
    bytes = output.toBytes();

问题2、Exception in thread “main” com.esotericsoftware.kryo.KryoException: Encountered unregistered class ID: 95

解决:参考 https://www.2cto.com/kf/201805/743957.html

①、用id代替类信息的模式不建议使用,而且,默认该功能也是关闭的,除非你在代码中显性的调用了以下代码: kryo.register(SomeClass.class); 或者: Kryo.setRegistrationRequired(true); 所以遇到Encountered unregistered class ID之类的问题,首先要检查该功能是否被不经意的开启了 。

② 、就是对象太大,导致系列化结果不完整 ,必须在new Output对象的时候,指定更大的bufferSize,例如:

 Output output = new Output(byteArrayOutputStream, 100000000);

你可能感兴趣的:(Kryo)