六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 34|回复: 0

Hessian源码学习(七)Ref

[复制链接]

升级  34.67%

28

主题

28

主题

28

主题

秀才

Rank: 2

积分
102
 楼主| 发表于 2013-2-3 13:30:13 | 显示全部楼层 |阅读模式
今天重新看了一下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();// 检查是否已经序列化过该objectInteger 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序列化快的原因之一。
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表