龙空技术网

Java 序列化简单探析

凤梨先生 794

前言:

此刻看官们对“java序列化protobuf”大概比较注意,兄弟们都需要剖析一些“java序列化protobuf”的相关内容。那么小编同时在网上网罗了一些关于“java序列化protobuf””的相关文章,希望姐妹们能喜欢,咱们快快来学习一下吧!

在写Java程序过程中,不可避免的要做对象数据通信或者存储,通信中数据格式定义决定了客户端与服务器之间的数据能否正常交流,其实相当于定义了一套规则; 当前基于应用层的数据封装越来越多使用序列化(Serialization),虽然效率没有直接使用数据流的高,但处理和分析却方便很多;因此底层框架设计越来越多基于序列化数据通信,包括当下很流行的基于netty的nio,也支持多种序列化方式,包括json、protobuf和java的Serializable等。java的Serializable虽然效率不高,但原理还是非常值得学习的。今天我们简单研究一下。

Java序列化算法

序列化 (Serialization)是一种将对象通过一连串的字节描述的过程;反序列化(deserialization)是一种将这些字节重建成一个对象的过程。Java提供一种处理对象序列化的标准机制的序列化API。我们将通过一个实例来示范序列化以后的字节是如何描述一个对象的信息的。

在java中,一个对象能够序列化的前提是实现Serializable接口,Serializable接口没有方法,相当于把这个对象做了个标记。 被标记了Serializable的类生产的Class就能被序列化机制处理。

实现了序列化接口的类

下面写个简单的测试程序将它序列化和反序列化。

并将这些序列化结果输出到文件看看长啥样。

序列化测试代码

执行运行后控制台输出:

DeserializeValue:222:name

说明程序序列化和反序列化正常。

程序比较简单,大家应该能看懂,这边就不详细说明功能了。

序列化的结果数据如下:

序列化结果

其中有一些内容可以看出来,比如完整包名(com.examples.serialization.SerializableObject),

被序列化的字段(id,name),序列化类型java.lang.String。

而其它部分不可读,我们转成16进制看看:

16进制显示序列化结果

这个序列化结果占用了124个byte。

为啥会占用这么多呢?

分析如下:

AC ED 声明使用了序列化协议

00 05 序列化协议版本

73 声明这是一个新的对象

72 声明这里开始一个新Class

00 1E Class名字的长度

63 6F 6D 2E 65 78 61 6D 70 6C 65 2E 53 65 72 69 61 6C 69 7A 61 62 6C 65 4F 62 6A 65 63 74

对应于我们的包的完整名:com.example.SerializableObject

D0 4F 99 84 6B 67 DA BC 接下来8个byte是 序列化ID,随机生成

02 声明该对象支持序列化

00 02 该类所包含的域个数(我们ID和NAME)

49 域类型. 49 代表"I", 也就是Int

00 02 域名字的长度

69 64 域名字描述

4C 域的类型

00 04 域名字长度

6E 61 6D 65 域名字描述

74 代表一个new String.用String来引用对象

00 12 该String长度

4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B Lcontain;, JVM的标准对象签名表示法

表示java/lang/String

78 对象块结束的标志

70 代表该类没有超类了

00 00 00 DE id变量的值

74 代表一个String

00 04 该String长度

6E 61 6D 65 name的值

这样一个个字段下来,大家应该明白序列化过程中java所干得事情了

照这个规则,我们完全可以自己写一个序列化和反序列化算法,

更能够从这个算法中做出一些优化,

比如包名这东西对跨语言、跨平台根本没意义,我们可以从新制定规则,试序列化包更加精炼高效。

同样,这个分析过程也说明了,序列化过程中只是把属性内容序列化了,方法的东西不会被序列化。

后面附上源码,大家可以自己试试,水平有限,希望可以帮到大家。

(toutiao的代码格式根本不支持,大家将就着看看了)

package com.example;

import java.io.Serializable;

public class SerializableObject implements Serializable {

private int id = 0;

private String name = "object";

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return "SerializableObject{" +

"id=" + id +

", name='" + name + '\'' +

'}';

}

}

public class SerializationTest {public static void main(String[] args) {new SerializationTest().doTest();}public void doTest() {String fileName = "serialize.obj";SerializableObject testObj = new SerializableObject();try {testObj.setId(222);testObj.setName("name");ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName));out.writeObject(testObj);out.close();ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName));SerializableObject t = (SerializableObject) in.readObject();in.close();System.out.println("DeserializeValue:"+testObj.getId()+":"+testObj.getName());} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}}}

标签: #java序列化protobuf