今天重新看了一下Hessian的序列化类,发现了一个之前被自己忽略的地方,而这应该也是Hessian序列化较快的原因之一(参考源码3.0.13)。
在大多数序列化类开始之前都有这么一段代码:
if (out.addRef(obj))
return;
//省略具体序列化code...
我们看下addRef(obj)做了些什么?
从代码注视中,我们也能看出它的含义:如果当前对象已经被序列化,那么此次我们只序列化它的引用)
/**
* If the object has already been written, just write its ref.
*
* @return true if we're writing a ref.
*/
public boolean addRef(Object object)
throws IOException
{
// 创建IdentityHashMap(简单来说它与hashMap的区别是比较两个对象是否相等一个是用equals,一个是用==)
if (_refs == null)
_refs = new IdentityHashMap();
// 检查是否已经序列化过该object
Integer ref = (Integer) _refs.get(object);
// 已经序列化过,则只需要序列化该object的一个标识(一个整型值)
if (ref != null) {
int value = ref.intValue();
writeRef(value);
return true;
}
// 第一次序列化该对象,则存入该object的标示(当前map.size)
else {
_refs.put(object, new Integer(_refs.size()));
return false;
}
}
public void writeRef(int value)
throws IOException
{
os.write('R');
os.write(value >> 24);
os.write(value >> 16);
os.write(value >> 8);
os.write(value);
}
这样子当序列化同一个对象时(即引用相同),第二次序列化只是序列化该对象的标识(一个整型值),并且在IdentityHashMap中存放所有对象的标识!
我们具体看一个例子:
OutputStream os = new FileOutputStream("hessianOutput");
AbstractHessianOutput out = new HessianOutput(os);
out.setSerializerFactory(new SerializerFactory());
Boolean[] array = new Boolean[]{true,false};
// 对于同一个对象序列化2次
out.writeObject(array);
out.writeObject(array);
我们看一下序列化的结果:
土黄色划线部分我想大家只要看过前面的文章都能分析出来,蓝色部分表示引用(ref)
可以看到第二次序列化时,由于之前已经序列化该对象所以这次只是序列化该对象的一个标识,对照前面代码可以知道是0;
序列化我们说到这里,但是现在又有一个问题,在反序列化的时候是如何处理这些对象标识的呢? 那我们就来看下HessianInput.readOject(cl):
/**
* Reads an object from the input stream with an expected type.
*/
public Object readObject(Class cl)
throws IOException
{
if (cl == null || cl == Object.class)
return readObject();
int tag = read();
switch (tag) {
// 如果是一个引用标识:
case 'R':
{
// 读取标记值(比如刚才例子那段代码就是0)
int ref = parseInt();
// 返回对象
return _refs.get(ref);
}
}
也许大家会对_refs.get(ref)有点疑问,_refs其实是一个ArrayList,每当反序列化读取一个对象时,就会把这个对象放入_refs中,那么当下次反序列化同一个对象时就可以直接从ArrayList中获取
这个特性我想也是Hessian序列化快的原因之一。
- 大小: 37.2 KB
分享到:
相关推荐
公司搞soa治理,正好采用hessian的export暴露接口,我修改了下,客户端不需要采用url,直接采用servicename,从zookeeper取地址列表。客户端和服务端通过mina通讯,不采用原生的http协议。目前mina的编码解码还有待...
hessian源码
Hessian 4.0.7 Jar 源码, Hessian 4.0.7 Jar 源码, Hessian 4.0.7 Jar 源码
项目选定Hessian作为web service的实现方式,确实很轻量级,速度就跟直接用socket差不多,全是二进制传送节约了不少开销。但是在使用过程中有业务需要是必须获得远程端的ip地址,主机名等信息的。翻便Hessian的文档...
Hessian的学习笔记
hessian-3.2.0源码,在做分布式交互时,可能要重写hessian
在android与web端实现hessian通信,源码为android客户端源码,jar包来自http://hsrong.iteye.com/blog/1719996,google官网提供的hessdroid不可用,因为里面包含一些android不支持的类;hessian官网的jar包适用于web...
想学习Hessian的同志们,这个是一个简单的demo。比较简单,不过能够加深对Hessian的理解
使用HessianCSharp编写的服务端与客户端,使用最少量的代码实现Hello
这是一个Hessian入门学习的实例,程序包是一个web工程,使用intellij idea + Maven开发,其中通过两个方式展示了使用Hessian实现RMI的原理,一个是访问jsp页面,一个是在代码中手工创建client。对于Hessian Servlet...
hessian最新源码分析.pdf
hessian3.0.1.jar, 可以和spring1.x集成,不会报错
hessian学习实例,hessian框架例子,与Spring集成。包括了server端和client端
hessian php与java通讯demo源码
Hessian是一个轻量级的remotingonhttp工具,使用简单的方法提供了RMI的功能。相比Webservice,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合发送二进制数据。
dubbo源码依赖hessian_lite,可以使用mvn install命令将jar包安装到本地的maven仓库
该案例有hessian java python,该案例有hessian java python,该案例有hessian java python
NULL 博文链接:https://qinghua0208.iteye.com/blog/493516
Hessian多个版本下载,包括Hessian3.1.6,Hessian3.2.1,Hessian4.0.7
Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能。 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。