当方法返回的类型未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框架的基础知识,它是一个高效的二进制序列化协议,广泛应用于Java和.NET之间跨语言通信。通过学习Hessian,我们可以更有效地处理数据传输,提高应用性能。 首先,让我们理解什么是序列化。...
3. 调用:通过代理对象调用服务接口的方法,Hessian会自动完成网络通信和序列化/反序列化操作。 五、示例——rpc4j-sample-web "rpc4j-sample-web"这个压缩包文件很可能是Hessian RPC的一个示例项目。通常,它会...
除了Java标准库提供的序列化机制外,还有其他流行的序列化框架,如Hessian和Apache Mina。这些框架提供了更高效的序列化和反序列化机制,适用于高性能网络通信场景。 #### 工作中需要注意的点 在实际开发中,使用...
本文将对五种常见的快速序列化框架——Google Protobuf、Apache Thrift、Hessian、Avro 和 Kryo 进行详细介绍,并对其性能进行比较。 #### 二、各框架详解 ##### 1. Google Protobuf - **简介**:由Google开发并...
`hessian-4.0.7.jar`是Hessian的核心库文件,它包含了Hessian协议的各种实现,包括序列化和反序列化的类和接口。开发者可以将这个jar包添加到项目类路径中,以便在Java应用程序中使用Hessian进行数据传输。该库支持...
1. **序列化与反序列化**:Hessian提供了高效的序列化和反序列化机制,能够将Java对象转换为字节流,然后在网络上传输。到达目的地后,这些字节流再被反序列化回原来的对象。这种机制大大减少了数据传输的开销。 2. ...
Hessian基于HTTP协议,通过序列化和反序列化Java对象,允许服务器端的方法被客户端直接调用,就像它们在同一台机器上运行一样。Hessian协议处理了类型转换和网络编码,使得跨平台通信变得简单,支持Java、C++、.NET...
【标签】:“源码”标签暗示笔记中可能包含了Hessian的源代码分析,帮助读者理解其内部机制,如何处理序列化、反序列化,以及如何实现远程调用的细节。“工具”标签则可能意味着笔记中介绍了一些辅助工具,用于测试...
4. **序列化和反序列化(Serialization & Deserialization)**:RPC框架需要将对象转换为可传输的格式(如二进制、XML、JSON等),以便在网络中传输。序列化是将对象转化为字节流的过程,反序列化则是将字节流还原为...
4. **Hessian序列化失败:HessianRuntimeException** 序列化问题通常与参数类型有关。确保所有传递的参数实现了`Serializable`接口,且避免使用Hessian特殊处理的类(如Number、Date、ArrayList、HashMap等)作为...
Dubbo提供了丰富的API和配置选项,允许开发者自定义服务行为,例如,可以通过XML配置或注解方式来声明服务接口和实现,同时支持多种序列化方式,如Hessian、FastJson等,以及多种通信协议,如HTTP、TCP等。...
- **序列化方式**:Hessian - **应用场景**:适用于需要处理大量并发请求的服务调用场景,特别是在消费者数量远超提供者的情况下,可以有效减少资源消耗。 - **优点**:高性能、低延迟。 - **缺点**:不适用于传输大...
微服务实践-服务框架Pigeon的设计与实现 服务框架Pigeon概述 美团大众点评微服务实践中,服务框架Pigeon扮演...Pigeon提供了基于Hessian和Thrift的序列化机制,通过Netty实现自定义TCP协议格式,开发成本低,性能高。
版本和分组管理是Dubbo提供的功能之一,它支持不同服务的分组管理和同服务多版本管理,且支持多种通讯协议(如Dubbo、Hessian、Thrift、RMI)和序列化协议(如Hessian2、JSON等)。负载均衡方面,Dubbo内建了随机、...
- RPC原理:深入理解远程过程调用的工作流程,包括请求的序列化、网络传输、反序列化和响应处理。 - Dubbo调用协议:分析Dubbo支持的多种调用协议(如HTTP、RMI、Hessian、Protobuf等),及其优缺点。 4. **服务...
nfs-rpc可能支持多种序列化方式,如JSON、Protobuf或Hessian等,每种方式在性能和兼容性上都有所不同。 5. **负载均衡**:为了提高可用性和性能,nfs-rpc可能内置了负载均衡策略,如轮询、随机、最少连接数等。当有...
2. 高效序列化库:如protobuf、Hessian、Kryo等,以减少网络传输的数据量,提升性能。 3. 路由与负载均衡:通过负载均衡算法,如轮询、权重轮询、一致性哈希等,将请求分发到合适的服务器。 4. 服务注册与发现:...
Netty Rpc支持多种序列化框架,如Hessian、Protobuf和Jackson等。 6. **负载均衡**:在高并发场景下,Netty Rpc可能会引入负载均衡策略,如轮询、随机或者根据服务的健康状态进行负载分配,确保系统的稳定性和响应...
此外,Dubbo还支持多种序列化协议,如Hessian、Java序列化等,以适应不同的性能和兼容性需求。 3. **负载均衡**:Dubbo支持多种负载均衡策略,如Random、RoundRobin、LeastActive等,可以在多台服务器间智能分配...
6. 序列化框架:默认使用Hessian序列化,了解其他如Java自带序列化等。 7. 服务失效踢出原理:服务健康检查失败后,服务提供者会从注册中心中移除服务实例。 8. 服务上线不影响旧版本:Dubbo支持服务降级和分组等...