首页 > 代码库 > 针对工作中的需要对已有的Java序列化工具分析
针对工作中的需要对已有的Java序列化工具分析
针对java原生序列化,以及优化过的java序列化工具列举说明。自己定义的类名(IOSerializable)、(Fast Serialization)、(FastjsonSerializable)
1、java序列化简介
序列化就是指对象通过写出描述自己状态的数值来记录自己的过程,即将对象表示成一系列有序字节,Java提供了将对象写入流和从流中恢复对象的方法。对象能包含其它的对象,而其它的对象又可以包含另外的对象。JAVA序列化能够自动的处理嵌套的对象。对于一个对象的简单域,writeObject()直接将其值写入流中。当遇到一个对象域时,writeObject()被再次调用,如果这个对象内嵌另一个对象,那么,writeObject()又被调用,直到对象能被直接写入流为止。程序员所需要做的是将对象传入ObjectOutputStream的writeObject()方法,剩下的将有系统自动完成。
要实现序列化的类必须实现的java.io.Serializable或java.io.Externalizable接口,否则将产生一个NotSerializableException。该接口内部并没有任何方法,它只是一个"tagging interface",仅仅"tags"它自己的对象是一个特殊的类型。类通过实现 java.io.Serializable接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。Java的"对象序列化"能让你将一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象时候,你就能把这些byte数据恢复出来,并据此重新构建那个对象了。
我们可以通过图片进行对比
反序列化 序列化
2、java序列化目的
- 支持运行在不同虚拟机上不同版本类之间的双向通讯;
- 定义允许JAVA类读取用相同类较老版本写入的数据流的机制;
- 定义允许JAVA类写用相同类较老版本读取的数据流的机制;
- 提供对持久性和RMI的序列化;
- 产生压缩流且运行良好以使RMI能序列化;
- 辨别写入的是否是本地流;
- 保持非版本化类的低负载;
3、序列化异常
序列化对象期间可能抛出6种异常:
- InvalidClassException 通常在重序列化流无法确定类型时或返回的类无法在取得对象的系统中表示时抛出此异常。异常也在恢复的类不声明为public时或没有public缺省(无变元)构造器时抛出。
- NotSerializableException 通常由具体化对象(负责自身的重序列化)探测到输入流错误时抛出。错误通常由意外不变量值指示,或者表示要序列化的对象不可序列化。
- StreamCorruptedException 在存放对象的头或控制数据无效时抛出。
- OptionalDataException 流中应包含对象但实际只包含原型数据时抛出。
- ClassNotFoundException 流的读取端找不到反序列化对象的类时抛出。
- IOException 要读取或写入的对象发生与流有关的错误时抛出。
4、java序列化工具分析
1、java原生序列化工具
a、自定义User类来作为列举
1 package dao; 2 3 import java.io.Serializable; 4 5 /** 6 * Created by guoyunlong on 2017/4/22 0022. 7 */ 8 public class User implements Serializable { 9 private String name; //用户姓名 10 private String sex; //性别 11 private int age; //年龄 12 13 public User(String name, String sex, int age) { 14 this.name = name; 15 this.sex = sex; 16 this.age = age; 17 18 } 19 20 public String getName() { 21 return name; 22 } 23 24 public void setName(String name) { 25 this.name = name; 26 } 27 28 public String getSex() { 29 return sex; 30 } 31 32 public void setSex(String sex) { 33 this.sex = sex; 34 } 35 36 public int getAge() { 37 return age; 38 } 39 40 public void setAge(int age) { 41 this.age = age; 42 } 43 }
b、根据已有的IO流进行简单的对象序列化反序列化
1 package Serializable; 2 3 import dao.User; 4 5 import java.io.*; 6 7 /** 8 * Created by guoyunlong on 2017/4/22 0022. 9 * 简单的Io-serializable序列化 10 */ 11 public class IoSerializable { 12 13 //序列化对象 14 public void writeMethod(String fileName,User user) { 15 ObjectOutputStream objectOutputStream = null; 16 try { 17 objectOutputStream = new ObjectOutputStream(new FileOutputStream(fileName)); 18 //序列化对象 19 objectOutputStream.writeObject(user); 20 21 } catch (IOException e) { 22 e.printStackTrace(); 23 } finally { 24 if(objectOutputStream !=null){ 25 //关闭输出流 26 try{ 27 objectOutputStream.close(); 28 }catch (IOException e){ 29 e.printStackTrace(); 30 } 31 } 32 33 } 34 } 35 36 //反序列对象得到数据 37 public User readMethod(String fileName){ 38 ObjectInputStream objectInputStream = null; 39 User user= null; 40 try { 41 objectInputStream = new ObjectInputStream(new FileInputStream(fileName)); 42 user =(User)objectInputStream.readObject(); 43 //输出对象 44 System.out.println("姓名"+user.getName()); 45 System.out.println("性别"+user.getSex()); 46 System.out.println("年龄"+user.getAge()); 47 48 }catch (IOException E){ 49 E.printStackTrace(); 50 }catch (ClassNotFoundException e){ 51 e.printStackTrace(); 52 } 53 finally { 54 if (objectInputStream != null) { 55 try { 56 objectInputStream.close(); 57 } catch (IOException E) { 58 E.printStackTrace(); 59 } 60 } 61 } 62 return user; 63 } 64 65 }
2、优化过的java序列化工具
a、FST fast-serialization
fastserialization是重新实现的 Java 快速对象序列化的开发包。序列化速度更快(2-10倍)、体积更小,而且兼容 JDK 原生的序列化。要求 JDK 1.7 支持。
Maven:download non-maven build at the releases section: https://github.com/RuedigerMoeller/fast-serialization/releases/
1 Maven配置 2 <dependency> 3 <groupId>de.ruedigermoeller</groupId> 4 <artifactId>fst</artifactId> 5 <version>1.58</version> 6 </dependency>
具体的实现类-FstSerializable
1 package Serializable; 2 3 import dao.User; 4 import de.ruedigermoeller.serialization.FSTConfiguration; 5 import de.ruedigermoeller.serialization.FSTObjectInput; 6 import de.ruedigermoeller.serialization.FSTObjectOutput; 7 8 import java.io.InputStream; 9 import java.io.OutputStream; 10 11 /** 12 * Created by guoyunlong on 2017/4/22 0022. 13 * Fst-fast-serialization序列化工具 14 * 15 */ 16 17 public class FstSerializable { 18 //得到FST配置上下文 19 static FSTConfiguration configuration =FSTConfiguration.createDefaultConfiguration(); 20 //得到反序列化出来的类和数据 21 //TODO USER 22 public Object ReadMethod(InputStream inputStream) throws Exception{ 23 FSTObjectInput in =configuration.getObjectInput(inputStream); 24 Object o =in.readObject(); 25 System.out.print(o); 26 inputStream.close(); 27 return o; 28 } 29 //序列化对象写进FST 30 public void WriteMethod(OutputStream outputStream,Object o ) throws Exception{ 31 FSTObjectOutput out =configuration.getObjectOutput(outputStream); 32 //当使用工厂方法时候 输出流不要关闭 33 out.writeObject(o); 34 out.flush(); 35 outputStream.close(); 36 37 38 } 39 }
b、JSON-fastJsonSerializable
jar包需要自己去下载这里没做过多说明
1 package Serializable; 2 3 import com.alibaba.fastjson.JSON; 4 import com.alibaba.fastjson.JSONObject; 5 import com.alibaba.fastjson.TypeReference; 6 import dao.User; 7 8 import java.util.List; 9 import java.util.Map; 10 11 /** 12 * Created by guoyunlong on 2017/4/22 0022. 13 * fastJson 序列化反序列化工具 14 */ 15 public class fastJsonSerializable { 16 17 //序列化简单对象-json- 18 //TODO String 19 public void jsonMethod(User user) { 20 //序列化 以对象为例 21 String txt = JSON.toJSONString(user); 22 System.out.println(txt); 23 //反序列化 几种类型 24 JSONObject json = JSON.parseObject(txt); 25 // JavaBean类型 26 User user1 = JSON.parseObject(txt, User.class); 27 28 // List<JavaBean>类型 29 30 List<User> listPerson =JSON.parseArray(txt, User.class); 31 32 // List<String>类型 33 34 List<String> listString = JSON.parseArray(txt, String.class); 35 36 //List<Map<String,Object>>类型 37 38 List<Map<String, Object>> listMap = JSON.parseObject(txt, new TypeReference<List<Map<String,Object>>>(){}); 39 System.out.println(json.getClass()); 40 } 41 42 }
5、最后总结
我只列举了自己现在可能会用的序列化工具。就已有原先使用Java原生序列化方案的系统来说,fst-serializer是良好的java原生序列化方案替代者,不仅体现再编程简单,而且速度与性能上会有大幅提升,只需替代output/inputstream 即可,性能的提升上也很可观。如果程序本身就用json格式序列化,则可以考虑引入一个性能优异的json解析库,一般再服务端jackson是广受欢迎的解析库,但是其1.1mb的jar包大小对一般的Android应用有点奢侈,而fastjson在Android上的表现似乎没有再JDK上那么好,不过也比大多数解析库快了。protobuffer更多的是一种取代xml的夸语言的消息交换格式,尽快速度很快,但是编程上需要定义消息格式,对成员变量多、业务复杂的javabean来说代价是较为复杂的,对稳定的已有系统来说总体代价较高。下表是原有的的各项指标的一个对比
序列化工具 | 序列化速度 | 序列化文件大小 | 编程模型复杂度 | 社区活跃度 | jar包大小 |
kryo | 极快 | 小 | 简单 | 高 | 132kb |
fst-serializer | 快 | 小 | 非常简单 | 高 | 246kb |
protobuffer | 快 | 较大 | 较复杂 | 稳定 | 329kb |
fastjson | 较快 | 较大 | 简单 | 一般 | 338kb |
jackson | 一般 | 较大 | 简单 | 稳定 | 1.1mb |
gson | 较慢 | 较大 | 简单 | 稳定 | 189kb |
6、参考博客:
Java序列化机制介绍及简单优化方法: http://www.javacodegeeks.com/2010/07/java-best-practices-high-performance.html
Java序列化“最佳”实践: http://www.javacodegeeks.com/2010/07/java-best-practices-high-performance.html
提升Java序列化的几种方法: http://www.javacodegeeks.com/2013/09/speed-up-with-fast-java-and-file-serialization.html
详细的Java序列化过程: http://blog.csdn.net/zhaozheng7758/article/details/7820018
Unsafe类型的Java序列化方法:http://www.javacodegeeks.com/2012/07/native-cc-like-performance-for-java.html
protobuf介绍1:http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/
protobuf介绍2:http://www.cnblogs.com/royenhome/archive/2010/10/29/1864860.html
针对工作中的需要对已有的Java序列化工具分析