今天重新看了一下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
分享到:
相关推荐
在Spring框架中集成Hessian是为了实现远程方法调用(Remote Method Invocation, RMI),这是一种轻量级的序列化协议,可以高效地传输Java...通过深入学习和实践,我们可以更好地利用Hessian来构建高性能的分布式系统。
2. Hessian的安全策略:学习如何在Hessian服务上实现认证和授权,防止未授权访问。 3. 性能优化:通过调整Hessian配置,如连接池大小、超时时间等,来提升服务性能。 4. 异常处理:研究如何处理Hessian通信过程中的...
<hessian:service id="userServiceHessian" interface="com.example.UserService" ref="userService"/> ``` 5. 启动Hessian服务:通常我们需要一个Servlet容器(如Tomcat)运行Spring应用,Hessian服务会注册到特定...
接着,下载dubbox-master源码,这包含了Dubbox的完整实现和示例代码。解压后,你可以在IDEA或Eclipse这样的集成开发环境中导入项目,进行编译和运行。 详细配置文档通常会涵盖以下几个方面: 1. **服务提供者配置*...
wangtengfei-hn_EmployeesExample_23540_1745868671962
scratch少儿编程逻辑思维游戏源码-汽车冲突.zip
scratch少儿编程逻辑思维游戏源码-棱镜.zip
少儿编程scratch项目源代码文件案例素材-直升机坠毁.zip
输入法优化与定制_五笔编码编辑与词库管理_Rime输入法引擎与86极点码表_跨平台五笔码表编辑器工具_for_macOS与Windows系统_支持用户自定义词条添加删除与排序_提供
少儿编程scratch项目源代码文件案例素材-主题乐园大亨.zip
scratch少儿编程逻辑思维游戏源码-迷失在像素平原.zip
少儿编程scratch项目源代码文件案例素材-纸格通关 云变量.zip
wanjunshe_Python-Tensorflow_12888_1745868924470
scratch少儿编程逻辑思维游戏源码-深入海底.zip
驾校自动化_网页自动化爬虫技术_Python27多线程HTTP请求模拟_龙泉驾校2014版约车系统自动预约助手_通过模拟登录和循环请求实现自动约车功能_支持失败自动递增车号重试_
scratch少儿编程逻辑思维游戏源码-南瓜危机.zip
scratch少儿编程逻辑思维游戏源码-皮博冒险者.zip
基于c++开发的网络嗅探器,重点对TCP、UDP、ARP、IGMP、ICMP 等数据包进行分析,实现捕捉前过滤、数据包统计、流量统计等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于c++开发的网络嗅探器,重点对TCP、UDP、ARP、IGMP、ICMP 等数据包进行分析,实现捕捉前过滤、数据包统计、流量统计等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档~ 基于c++开发的网络嗅探器,重点对TCP、UDP、ARP、IGMP、ICMP 等数据包进行分析,实现捕捉前过滤、数据包统计、流量统计等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于c++开发的网络嗅探器,重点对TCP、UDP、ARP、IGMP、ICMP 等数据包进行分析,实现捕捉前过滤、数据包统计、流量统计等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于c++开发的网络嗅探器,重点对TCP、UDP、ARP、IGMP、ICMP 等数据包进行分析,实现捕捉前过滤、数据包统计、流量统计等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档
用于释放电脑的内存,很好用。
scratch少儿编程逻辑思维游戏源码-气球足球.zip