`
DiaoCow
  • 浏览: 244382 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Hessian源码学习(四)BasicSerializer分析

 
阅读更多
之前分析了序列化一个对象的流程,基本上可以归纳成先获取一个对象的序列化类,然后由该序列化类来序列化对象;那么究竟有哪些序列化类,以及这些类是如何序列化的就是我们本次分析的重点(参考源码版本3.0.13)!

先看下整个序列化类的的类图:




可以看出:
1.它们都是AbstractSerializer的子类;
2.实现序列化的方法是:void writeObject(Object obj, AbstractHessianOutput out)方法;

现在我们就分别讨论这些类的实现,首先是BasicSerializer类(用来序列化java基本类型,以及基本类型数组)

Integer obj = new Integer(10);
// 这里得到的就是:BasicSerializer(理由请看上一篇分析)
serializer = _serializerFactory.getSerializer(obj.getClass());
serializer.writeObject(obj, this);

现在我们看下BasicSerializer的writeObject方法:
public void writeObject(Object obj, AbstractHessianOutput out)
	throws IOException
{
    switch (code) {
	// 针对每一种类型,做出相应的序列化
    case BOOLEAN:
     
	// 省略后面代码...

    default:
      throw new RuntimeException(code + " " + String.valueOf(obj.getClass()));
    }
}



1.现在我们详细的看一下每一种类型如何序列化,首先看下boolean/Boolean
 case BOOLEAN:
      out.writeBoolean(((Boolean) obj).booleanValue());
      break;

writeBoolean方法的实现还是比较简单的,如果是true就输出'T',否则输出'F'

public void writeBoolean(boolean value)
    throws IOException
{
    if (value)
      os.write('T');
    else
      os.write('F');
}

我们看下例子:
out.writeObject(true);




2.序列化 byte, short, int(包括相应的对象类型):
 case BYTE:
 case SHORT:
 case INTEGER:
      out.writeInt(((Number) obj).intValue());
      break;

发现没,对于byte, short都是当做int来序列化!

writeInt的输出格式为:‘I’ b32 b24 b16 b8 (b32代表从第32位开始的8位, b24代表从第24位开始的8位,后面以此类推)

public void writeInt(int value)
    throws IOException
{
    os.write('I');
    os.write(value >> 24);
    os.write(value >> 16);
    os.write(value >> 8);
    os.write(value);
}

我们看一个例子:
int intValue = 1234;
out.writeObject(intValue);


short shortVale = 300;
out.writeObject(shortVale);




3.序列化long(包括相应的对象类型)
case LONG:
	out.writeLong(((Number) obj).longValue());
	break;

writeLong的输出格式为:'L' b64 b56 b48 b40 b32 b24 b16 b8

public void writeLong(long value)
    throws IOException
{
    os.write('L');
    os.write((byte) (value >> 56));
    os.write((byte) (value >> 48));
    os.write((byte) (value >> 40));
    os.write((byte) (value >> 32));
    os.write((byte) (value >> 24));
    os.write((byte) (value >> 16));
    os.write((byte) (value >> 8));
    os.write((byte) (value));
}



4.序列化float, double(包括相应的对象类型)
case FLOAT:
case DOUBLE:
      out.writeDouble(((Number) obj).doubleValue());
      break;

从这里我们也可以看出,float也是当做double类型序列化

另外writeDouble的输出格式为:'D' b64 b56 b48 b40 b32 b24 b16 b8

public void writeDouble(double value)
    throws IOException
{
    long bits = Double.doubleToLongBits(value);
    
    os.write('D');
    os.write((byte) (bits >> 56));
    os.write((byte) (bits >> 48));
    os.write((byte) (bits >> 40));
    os.write((byte) (bits >> 32));
    os.write((byte) (bits >> 24));
    os.write((byte) (bits >> 16));
    os.write((byte) (bits >> 8));
    os.write((byte) (bits));
}

我汇总long,double来看一个例子:
long longValue = 1234567L;
double doubleValue = 1.2345D;
out.writeObject(longValue);
out.writeObject(doubleValue);




5.字符char和字符串String的序列化
case CHARACTER:
      out.writeString(String.valueOf(obj));
      break;
      
case STRING:
      out.writeString((String) obj);
      break;

可以看到char和String都是使用writeString方法进行序列化,序列化格式为:'S' 字符串长度 字符串每个字符的值

public void writeString(String value)
    throws IOException
{
    if (value == null) {
      os.write('N');
    }
    else {
      int length = value.length();
      int offset = 0;
      
	  // 这里一段while循环我暂时没有深究,大概是对超长字符串的输出处理
      while (length > 0x8000) {
        int sublen = 0x8000;

		char tail = value.charAt(offset + sublen - 1);

		if (0xd800 <= tail && tail <= 0xdbff)
		  sublen--;
		    
		    os.write('s');
		    os.write(sublen >> 8);
		    os.write(sublen);

		    printString(value, offset, sublen);

		    length -= sublen;
		    offset += sublen;
		}
	  
	  // 输出:'S' 字符串长度
      os.write('S');
      os.write(length >> 8);
      os.write(length);

	   // 输出:字符串中每个字符的值
      printString(value, offset, length);
    }
}

我们还是看一个例子比较直观:
String strValue = "Hello Hessian!";
out.writeObject(strValue);




上面我们基本已经讲了基本类型和相应的对象类型序列化,现在我们来看下相应的数组类型的序列化;

数组序列化格式比较简单,基本上可以归纳为:'Vt' 长度 '[数组类型'  'l'  数组长度  数组元素...  'z'
我们仅以long型数组为例:
 case LONG_ARRAY:
    {
	  // 关于这个ref目前可以忽略,后面的文章会说明
      if (out.addRef(obj))
        return;
      
      long []data = (long []) obj;
	  // 输出数组格式头:'Vt' 长度5 '[long' 'l' 数组长度  
      out.writeListBegin(data.length, "[long");
      for (int i = 0; i < data.length; i++)
		// 输出数组中每一个元素(看看这里是不是很熟悉?对,就是我们刚才分析的那些)
        out.writeLong(data[i]);
	  // 输出结束标记: 'z'
      out.writeListEnd();
      break;
    }

我们具体看下writeListBegin 和 writeListEnd的实现

public boolean writeListBegin(int length, String type)
    throws IOException
{
    os.write('V');

    if (type != null) {
      os.write('t');
      printLenString(type);
    }

    if (length >= 0) {
      os.write('l');
      os.write(length >> 24);
      os.write(length >> 16);
      os.write(length >> 8);
      os.write(length);
    }

    return true;
}

public void writeListEnd()
	throws IOException
{
	os.write('z');
}

话不多说,上代码
long[] arrayLong = new long[] { 12345L, 1234L, 789L };
out.writeObject(arrayLong);



关于序列化基本类型数组,还有两点需要注意

1.序列化short类型数组,虽然type标记是[short,但是其中的每一个元素还是当做int来序列化,同理对于float型数组,标记为[float,但是对于每一个元素时当做double来序列化;

2.byte类型数组的序列化比较特殊,他基本当成了一个String来输出,只是开始标记为'B'


总结

1.BasicSerializer可以序列化哪些类型?(主要是java基本类型,基本类型数组(包括相应的对象类型);

2.对于每一种的序列化格式是什么?

最后我自己制作了一个表格,大致叙说了各个类型的序列化格式:

  • 大小: 12.7 KB
  • 大小: 120.8 KB
  • 大小: 14 KB
  • 大小: 18.4 KB
  • 大小: 16.4 KB
  • 大小: 24.6 KB
  • 大小: 24.6 KB
  • 大小: 47.7 KB
  • 大小: 83.1 KB
1
1
分享到:
评论

相关推荐

    hessian源码修改,包含了协议的修改

    公司搞soa治理,正好采用hessian的export暴露接口,我修改了下,客户端不需要采用url,直接采用servicename,从zookeeper取地址列表。客户端和服务端通过mina通讯,不采用原生的http协议。目前mina的编码解码还有待...

    Hessian源码分析和Hack.doc

    《Hessian源码分析与Hack:携带远程调用端信息》 Hessian作为一种轻量级的RPC(远程过程调用)框架,因其高效、简洁的二进制协议,被广泛应用于构建Web服务。然而,在实际应用中,有时我们需要获取到远程调用端的IP...

    Hessian多个版本打包下载

    这个压缩包包含了Hessian的多个版本,分别是Hessian3.1.6、Hessian3.2.1以及Hessian4.0.7。每个版本都有其特定的功能改进和优化,了解这些版本的区别和适用场景对于开发者来说至关重要。 Hessian3.1.6是Hessian的一...

    hessian最新源码分析.pdf

    在深入分析Hessian的源码之前,我们先来理解一下Hessian是什么。Hessian是一种二进制的Remoting协议,它允许Java应用通过HTTP进行高效、简洁的数据交换。Hessian客户端和服务端之间的通信基于HTTP协议,实现了远程...

    Hessian源码示例

    这个"**Hessian源码示例**"很可能包含了使用HessianCSharp库在C#环境中实现服务端和客户端通信的示例代码。HessianCSharp是.NET平台上的一个开源库,它实现了Hessian协议,使得开发者可以方便地在.NET应用程序之间...

    hessian学习基础篇——序列化和反序列化

    通过阅读和分析Hessian的源码,我们可以了解其如何编码和解码各种数据类型,以及如何优化序列化和反序列化的过程。这对于优化自定义序列化逻辑或者解决Hessian使用中遇到的问题非常有帮助。 总结起来,Hessian是一...

    Hessian 学习 例子 实例

    至于标签"源码",学习Hessian时查看源码有助于理解其内部工作原理,比如数据如何被编码和解码。你可以通过阅读开源的Hessian库,如Caucho Hessian的Java实现,来了解其底层细节。 至于"工具",有一些工具可以帮助...

    hessian-4.0.38-sources.jar

    hessian源码

    Hessian的学习笔记

    四、Hessian的优点 Hessian具有以下优点: * 高性能:Hessian基于Binary-RPC协议实现,具有高性能和低延迟。 * 轻量级:Hessian是轻量级的RPC解决方案,易于使用和部署。 * 跨语言支持:Hessian支持多种编程语言,...

    hessian-3.2.0源码

    hessian-3.2.0源码,在做分布式交互时,可能要重写hessian

    android实现Hessian通信源码

    在android与web端实现hessian通信,源码为android客户端源码,jar包来自http://hsrong.iteye.com/blog/1719996,google官网提供的hessdroid不可用,因为里面包含一些android不支持的类;hessian官网的jar包适用于web...

    Hessian-4.0.7(Jar包 + 源码)

    源码也使得开发者能够根据需要修改或扩展Hessian的功能,例如添加新的序列化策略,或者优化特定场景下的性能。 Hessian在实际应用中,通常被用来构建RPC(Remote Procedure Call)框架,使得服务端的方法可以直接在...

    Hessian

    对于深入理解Hessian的工作机制,阅读和分析源码是必不可少的。Caucho Technology提供了Hessian的开源实现,开发者可以通过阅读源码了解其内部细节,如序列化和反序列化的具体实现、类型转换逻辑等。 在博客链接...

    Hessian学习简单demo

    Hessian是一种二进制协议,它被设计用于提高远程调用的...通过学习和实践这个Hessian demo,你将能够更好地应对涉及远程调用和数据交换的问题。无论是Java开发者还是C++开发者,Hessian都是值得了解和掌握的一项技术。

    Nacos JRaft Hessian 反序列化 RCE 分析.pdf

    ### Nacos JRaft Hessian 反序列化 RCE 分析 #### 一、背景介绍 Nacos 是阿里巴巴开源的一款易于构建云原生应用的动态服务发现、配置管理和服务管理平台。JRafT 是 SOFAStack 微服务平台中的一个分布式一致性组件...

    Hessian学习入门实例

    这是一个Hessian入门学习的实例,程序包是一个web工程,使用intellij idea + Maven开发,其中通过两个方式展示了使用Hessian实现RMI的原理,一个是访问jsp页面,一个是在代码中手工创建client。对于Hessian Servlet...

    多尺度hessian滤波器图像增强

    通过计算图像每个像素位置的Hessian矩阵,我们可以分析其特征,例如检测图像中的血管、纹理或结构性边缘。 多尺度是指在不同分辨率下应用Hessian滤波器,这样可以更好地适应图像中的各种尺度特征。在小尺度上,...

    hessian学习实例

    在这个“hessian学习实例”中,我们将深入探讨Hessian框架的使用,特别是如何将其与Spring框架集成,以及如何构建server端和client端。 首先,让我们理解Hessian的工作原理。Hessian基于HTTP协议,它将Java对象序列...

    hessian php与java通讯demo源码

    总之,这个"PHP与Java通信Demo源码"是一个很好的学习资源,帮助开发者理解如何在PHP和Java之间使用Hessian协议进行通信。通过分析和实践这些示例代码,你可以更好地掌握Hessian的工作原理和使用方式,为你的跨语言...

    Hessian协议格式

    在示例代码中,我们将通过 Hessian protocol 调用这四个方法,并截取并分析请求报文和应答报文的格式。 2.1 Hessian 报文结构应用示例背景说明 在示例代码中,我们使用 Java 语言编写了一个简单的示例,用于形象地...

Global site tag (gtag.js) - Google Analytics