`
goon
  • 浏览: 184116 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

hessian——序列化

 
阅读更多

当方法返回的类型未implement  java.io.Serializable时,会throw exception;

原因: SerializerFactory中以下方法:

 /**
   * Returns the default serializer for a class that isn't matched
   * directly.  Application can override this method to produce
   * bean-style serialization instead of field serialization.
   *
   * @param cl the class of the object that needs to be serialized.
   *
   * @return a serializer object for the serialization.
   */
  protected Serializer getDefaultSerializer(Class cl)
  {
    if (_defaultSerializer != null)
      return _defaultSerializer;

    if (! Serializable.class.isAssignableFrom(cl)
        && ! _isAllowNonSerializable) {
      throw new IllegalStateException("Serialized class " + cl.getName() + " must implement java.io.Serializable");
    }
    
    if (_isEnableUnsafeSerializer
        && JavaSerializer.getWriteReplace(cl) == null) {
      return UnsafeSerializer.create(cl);
    }
    else
      return JavaSerializer.create(cl);
  }

 其中_isAllowNonSerializable默认为false。那如果返回的类型不想implement  java.io.Serializable 怎么办呢?

查看HessianServlet中的代码,没有修改SerializerFactory的_isAllowNonSerializable的值,也就是不能通过web.xml中的配置来设置这个开关了,所以只能使用自己继承HessianServlet的servlet了,然后在自定义的servlet中把SerializerFactory的_isAllowNonSerializable值改为true;

 

public boolean isAllowNonSerializable()

  {

    return _isAllowNonSerializable;

  }

再看看isAllowNonSerializable()被调用的情况,发现没有被任何对象调用,说明_isAllowNonSerializable只会在getDefaultSerializer()方法中起作用,也从另一方面说明hessian的序列化跟java.io.Serializable无关,只是有个_isAllowNonSerializable的开关而已,hessian实现了自己的序列号方式:

Hessian2Output.java:

 

/**
   * Writes any object to the output stream.
   */
  public void writeObject(Object object)
    throws IOException
  {
    if (object == null) {
      writeNull();
      return;
    }

    Serializer serializer
      = findSerializerFactory().getObjectSerializer(object.getClass());

    serializer.writeObject(object, this);
  }

 UnsafeSerializer.java:

 

 

 public void writeObject(Object obj, AbstractHessianOutput out)
    throws IOException
  {
    if (out.addRef(obj)) {
      return;
    }
    
    Class<?> cl = obj.getClass();

    int ref = out.writeObjectBegin(cl.getName());

    if (ref >= 0) {
      writeInstance(obj, out);
    }
    else if (ref == -1) {
      writeDefinition20(out);
      out.writeObjectBegin(cl.getName());
      writeInstance(obj, out);
    }
    else {
      writeObject10(obj, out);
    }
  }
 final public void writeInstance(Object obj, AbstractHessianOutput out)
    throws IOException
  {
    try {
      FieldSerializer []fieldSerializers = _fieldSerializers;
      int length = fieldSerializers.length;
      
      for (int i = 0; i < length; i++) {
        fieldSerializers[i].serialize(out, obj);   //序列化方法返回结果到输出流
      }
    } catch (RuntimeException e) {
      throw new RuntimeException(e.getMessage() + "\n class: "
                                 + obj.getClass().getName()
                                 + " (object=" + obj + ")",
                                 e);
    } catch (IOException e) {
      throw new IOExceptionWrapper(e.getMessage() + "\n class: "
                                   + obj.getClass().getName()
                                   + " (object=" + obj + ")",
                                   e);
    }
  }

 @Override
    final void serialize(AbstractHessianOutput out, Object obj)
      throws IOException
    {
      try {
        Object value = _unsafe.getObject(obj, _offset); //获取obj对象中的属性值
        
        out.writeObject(value);//把属性值写入out,由于属性值是基本类型(比如:字符串),则writeObject会调用字符串相应的serializer(BasicSerializer)的serialize(out, obj)方法(见后面)
      } catch (RuntimeException e) {
        throw new RuntimeException(e.getMessage() + "\n field: "
                                   + _field.getDeclaringClass().getName()
                                   + '.' + _field.getName(),
                                   e);
      } catch (IOException e) {
        throw new IOExceptionWrapper(e.getMessage() + "\n field: "
                                     + _field.getDeclaringClass().getName()
                                     + '.' + _field.getName(),
                                     e);
      }
    }

 基本类型对应的BasicSerializer的serializer(out,obj)方法:

 

 

public void writeObject(Object obj, AbstractHessianOutput out)
    throws IOException
  {
    switch (_code) {
    case BOOLEAN:
      out.writeBoolean(((Boolean) obj).booleanValue());
      break;
      
    case BYTE:
    case SHORT:
    case INTEGER:
      out.writeInt(((Number) obj).intValue());
      break;

    case LONG:
      out.writeLong(((Number) obj).longValue());
      break;

    case FLOAT:
    case DOUBLE:
      out.writeDouble(((Number) obj).doubleValue());
      break;
      
    case CHARACTER:
    case CHARACTER_OBJECT:
      out.writeString(String.valueOf(obj));
      break;
      
    case STRING:
      out.writeString((String) obj);
      break;
      
    case DATE:
      out.writeUTCDate(((Date) obj).getTime());
      break;
      
    case BOOLEAN_ARRAY:
    {
      if (out.addRef(obj))
        return;
      
      boolean []data = (boolean []) obj;
      boolean hasEnd = out.writeListBegin(data.length, "[boolean");
      for (int i = 0; i < data.length; i++)
        out.writeBoolean(data[i]);

      if (hasEnd)
	out.writeListEnd();
      
      break;
    }

    case BYTE_ARRAY:
    {
      byte []data = (byte []) obj;
      out.writeBytes(data, 0, data.length);
      break;
    }

    case SHORT_ARRAY:
    {
      if (out.addRef(obj))
        return;
      
      short []data = (short []) obj;
      boolean hasEnd = out.writeListBegin(data.length, "[short");
      
      for (int i = 0; i < data.length; i++)
        out.writeInt(data[i]);

      if (hasEnd)
	out.writeListEnd();
      break;
    }

    case INTEGER_ARRAY:
    {
      if (out.addRef(obj))
        return;
      
      int []data = (int []) obj;
      
      boolean hasEnd = out.writeListBegin(data.length, "[int");
      
      for (int i = 0; i < data.length; i++)
        out.writeInt(data[i]);

      if (hasEnd)
	out.writeListEnd();
      
      break;
    }

    case LONG_ARRAY:
    {
      if (out.addRef(obj))
        return;
      
      long []data = (long []) obj;
      
      boolean hasEnd = out.writeListBegin(data.length, "[long");
      
      for (int i = 0; i < data.length; i++)
        out.writeLong(data[i]);

      if (hasEnd)
	out.writeListEnd();
      break;
    }

    case FLOAT_ARRAY:
    {
      if (out.addRef(obj))
        return;
      
      float []data = (float []) obj;
      
      boolean hasEnd = out.writeListBegin(data.length, "[float");
      
      for (int i = 0; i < data.length; i++)
        out.writeDouble(data[i]);

      if (hasEnd)
	out.writeListEnd();
      break;
    }

    case DOUBLE_ARRAY:
    {
      if (out.addRef(obj))
        return;
      
      double []data = (double []) obj;
      boolean hasEnd = out.writeListBegin(data.length, "[double");
      
      for (int i = 0; i < data.length; i++)
        out.writeDouble(data[i]);

      if (hasEnd)
	out.writeListEnd();
      break;
    }

    case STRING_ARRAY:
    {
      if (out.addRef(obj))
        return;
      
      String []data = (String []) obj;
      
      boolean hasEnd = out.writeListBegin(data.length, "[string");
      
      for (int i = 0; i < data.length; i++) {
        out.writeString(data[i]);
      }

      if (hasEnd)
	out.writeListEnd();
      break;
    }

    case CHARACTER_ARRAY:
    {
      char []data = (char []) obj;
      out.writeString(data, 0, data.length);
      break;
    }

    case OBJECT_ARRAY:
    {
      if (out.addRef(obj))
        return;
      
      Object []data = (Object []) obj;
      
      boolean hasEnd = out.writeListBegin(data.length, "[object");
      
      for (int i = 0; i < data.length; i++) {
        out.writeObject(data[i]);
      }

      if (hasEnd)
	out.writeListEnd();
      break;
    }
    
    case NULL:
      out.writeNull();
      break;
    
    case OBJECT:
      ObjectHandleSerializer.SER.writeObject(obj, out);
      break;

    case BYTE_HANDLE:
      out.writeObject(new ByteHandle((Byte) obj));
      break;

    case SHORT_HANDLE:
      out.writeObject(new ShortHandle((Short) obj));
      break;

    case FLOAT_HANDLE:
      out.writeObject(new FloatHandle((Float) obj));
      break;

    default:
      throw new RuntimeException(_code + " unknown code for " + obj.getClass());
    }
  }

 再看看out怎么写基本类型的:

 

 

 public void writeBoolean(boolean value)
    throws IOException
  {
    if (SIZE < _offset + 16)
      flushBuffer();

    if (value)
      _buffer[_offset++] = (byte) 'T';
    else
      _buffer[_offset++] = (byte) 'F';
  }
public void writeInt(int value)
    throws IOException
  {
    int offset = _offset;
    byte []buffer = _buffer;

    if (SIZE <= offset + 16) {
      flushBuffer();
      offset = _offset;
    }

    if (INT_DIRECT_MIN <= value && value <= INT_DIRECT_MAX)
      buffer[offset++] = (byte) (value + BC_INT_ZERO);
    else if (INT_BYTE_MIN <= value && value <= INT_BYTE_MAX) {
      buffer[offset++] = (byte) (BC_INT_BYTE_ZERO + (value >> 8));
      buffer[offset++] = (byte) (value);
    }
    else if (INT_SHORT_MIN <= value && value <= INT_SHORT_MAX) {
      buffer[offset++] = (byte) (BC_INT_SHORT_ZERO + (value >> 16));
      buffer[offset++] = (byte) (value >> 8);
      buffer[offset++] = (byte) (value);
    }
    else {
      buffer[offset++] = (byte) ('I');
      buffer[offset++] = (byte) (value >> 24);
      buffer[offset++] = (byte) (value >> 16);
      buffer[offset++] = (byte) (value >> 8);
      buffer[offset++] = (byte) (value);
    }

    _offset = offset;
  }



public final void flushBuffer()
    throws IOException
  {
    int offset = _offset;

    OutputStream os = _os;

    if (! _isPacket && offset > 0) {
      _offset = 0;
      if (os != null)
        os.write(_buffer, 0, offset);
    }
    else if (_isPacket && offset > 3) {
      int len = offset - 3;
      _buffer[0] = (byte) 0x80;
      _buffer[1] = (byte) (0x80 + ((len >> 7) & 0x7f));
      _buffer[2] = (byte) (len & 0x7f);
      _offset = 3;

      if (os != null)
        os.write(_buffer, 0, offset);

      _buffer[0] = (byte) 0x56;
      _buffer[1] = (byte) 0x56;
      _buffer[2] = (byte) 0x56;

    }
  }

public final static int SIZE = 4096;

 可见项buffer中写数据前,都会判断_offset大写,如果足够大,则flushBuffer。

 

分享到:
评论

相关推荐

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

    本文将深入探讨Hessian框架的基础知识,它是一个高效的二进制序列化协议,广泛应用于Java和.NET之间跨语言通信。通过学习Hessian,我们可以更有效地处理数据传输,提高应用性能。 首先,让我们理解什么是序列化。...

    hessian轻量级 rpc实现

    3. 调用:通过代理对象调用服务接口的方法,Hessian会自动完成网络通信和序列化/反序列化操作。 五、示例——rpc4j-sample-web "rpc4j-sample-web"这个压缩包文件很可能是Hessian RPC的一个示例项目。通常,它会...

    Java 序列化的秘密(高清PDF中文版)

    除了Java标准库提供的序列化机制外,还有其他流行的序列化框架,如Hessian和Apache Mina。这些框架提供了更高效的序列化和反序列化机制,适用于高性能网络通信场景。 #### 工作中需要注意的点 在实际开发中,使用...

    快速序列化框架

    本文将对五种常见的快速序列化框架——Google Protobuf、Apache Thrift、Hessian、Avro 和 Kryo 进行详细介绍,并对其性能进行比较。 #### 二、各框架详解 ##### 1. Google Protobuf - **简介**:由Google开发并...

    hessian-4.0.7.jar + src

    `hessian-4.0.7.jar`是Hessian的核心库文件,它包含了Hessian协议的各种实现,包括序列化和反序列化的类和接口。开发者可以将这个jar包添加到项目类路径中,以便在Java应用程序中使用Hessian进行数据传输。该库支持...

    WebService另一种轻量级实现—Hessian 学习笔记.rar

    1. **序列化与反序列化**:Hessian提供了高效的序列化和反序列化机制,能够将Java对象转换为字节流,然后在网络上传输。到达目的地后,这些字节流再被反序列化回原来的对象。这种机制大大减少了数据传输的开销。 2. ...

    使用hessian进行服务器-客户端通讯

    Hessian基于HTTP协议,通过序列化和反序列化Java对象,允许服务器端的方法被客户端直接调用,就像它们在同一台机器上运行一样。Hessian协议处理了类型转换和网络编码,使得跨平台通信变得简单,支持Java、C++、.NET...

    Hessian笔记

    【标签】:“源码”标签暗示笔记中可能包含了Hessian的源代码分析,帮助读者理解其内部机制,如何处理序列化、反序列化,以及如何实现远程调用的细节。“工具”标签则可能意味着笔记中介绍了一些辅助工具,用于测试...

    dubbo——rpc简介1

    4. **序列化和反序列化(Serialization & Deserialization)**:RPC框架需要将对象转换为可传输的格式(如二进制、XML、JSON等),以便在网络中传输。序列化是将对象转化为字节流的过程,反序列化则是将字节流还原为...

    系统稳定性——Dubbo 常见错误及解决方法1

    4. **Hessian序列化失败:HessianRuntimeException** 序列化问题通常与参数类型有关。确保所有传递的参数实现了`Serializable`接口,且避免使用Hessian特殊处理的类(如Number、Date、ArrayList、HashMap等)作为...

    provider——consumer 程序源码.zip

    Dubbo提供了丰富的API和配置选项,允许开发者自定义服务行为,例如,可以通过XML配置或注解方式来声明服务接口和实现,同时支持多种序列化方式,如Hessian、FastJson等,以及多种通信协议,如HTTP、TCP等。...

    2021Java字节跳动面试题——面向字节_Dubbo(上).pdf

    - **序列化方式**:Hessian - **应用场景**:适用于需要处理大量并发请求的服务调用场景,特别是在消费者数量远超提供者的情况下,可以有效减少资源消耗。 - **优点**:高性能、低延迟。 - **缺点**:不适用于传输大...

    《美团大众点评微服务实践——服务框架-Pigeon-的设计与实现》.pdf

    微服务实践-服务框架Pigeon的设计与实现 服务框架Pigeon概述 美团大众点评微服务实践中,服务框架Pigeon扮演...Pigeon提供了基于Hessian和Thrift的序列化机制,通过Netty实现自定义TCP协议格式,开发成本低,性能高。

    阿里大牛眼中——Dubbo 的过去、现在以及未来

    版本和分组管理是Dubbo提供的功能之一,它支持不同服务的分组管理和同服务多版本管理,且支持多种通讯协议(如Dubbo、Hessian、Thrift、RMI)和序列化协议(如Hessian2、JSON等)。负载均衡方面,Dubbo内建了随机、...

    java面试——Dubbo面试专题.zip

    - RPC原理:深入理解远程过程调用的工作流程,包括请求的序列化、网络传输、反序列化和响应处理。 - Dubbo调用协议:分析Dubbo支持的多种调用协议(如HTTP、RMI、Hessian、Protobuf等),及其优缺点。 4. **服务...

    基于Java的实例源码-高性能RPC框架 nfs-rpc.zip

    nfs-rpc可能支持多种序列化方式,如JSON、Protobuf或Hessian等,每种方式在性能和兼容性上都有所不同。 5. **负载均衡**:为了提高可用性和性能,nfs-rpc可能内置了负载均衡策略,如轮询、随机、最少连接数等。当有...

    基于java的高性能RPC框架 nfs-rpc.zip

    2. 高效序列化库:如protobuf、Hessian、Kryo等,以减少网络传输的数据量,提升性能。 3. 路由与负载均衡:通过负载均衡算法,如轮询、权重轮询、一致性哈希等,将请求分发到合适的服务器。 4. 服务注册与发现:...

    Netty Rpc框架

    Netty Rpc支持多种序列化框架,如Hessian、Protobuf和Jackson等。 6. **负载均衡**:在高并发场景下,Netty Rpc可能会引入负载均衡策略,如轮询、随机或者根据服务的健康状态进行负载分配,确保系统的稳定性和响应...

    High_Performance_Remoting.rar

    此外,Dubbo还支持多种序列化协议,如Hessian、Java序列化等,以适应不同的性能和兼容性需求。 3. **负载均衡**:Dubbo支持多种负载均衡策略,如Random、RoundRobin、LeastActive等,可以在多台服务器间智能分配...

    1000道 互联网大厂Java工程师面试题.pdf

    6. 序列化框架:默认使用Hessian序列化,了解其他如Java自带序列化等。 7. 服务失效踢出原理:服务健康检查失败后,服务提供者会从注册中心中移除服务实例。 8. 服务上线不影响旧版本:Dubbo支持服务降级和分组等...

Global site tag (gtag.js) - Google Analytics