hessian 序列化 异常

      最近忙于业务迭代开发,没有太多时间思考。这两天,开发的时候遇到了一个hessian 序列化异常,拿出来记录一下分析的过程及解决方法。

      

      先上异常酷

      

2016-06-01 10:59:37 New I/O server worker #1-1 WARN  [com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation:112] -  [DUBBO] Decode argument failed: com.apricotforest.casefolder.medical.search.vo.MedicalRecordSearchVo.tagId: expected integer at 0x24 [B
 ([B@1e919697), dubbo version: 2.5.3, current host: 192.168.10.23com.alibaba.com.caucho.hessian.io.HessianFieldException: com.apricotforest.casefolder.medical.search.vo.MedicalRecordSearchVo.tagId: expected integer at 0x24 [B ([B@1e919697)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer.logDeserializeError(JavaDeserializer.java:671)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer$ObjectFieldDeserializer.deserialize(JavaDeserializer.java:400)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:233)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:157)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2067)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:1592)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:1576)
	at com.alibaba.dubbo.common.serialize.support.hessian.Hessian2ObjectInput.readObject(Hessian2ObjectInput.java:94)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:109)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:71)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec.decodeBody(DubboCodec.java:137)
	at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:126)
	at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:87)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCountCodec.decode(DubboCountCodec.java:46)
	at com.alibaba.dubbo.remoting.transport.netty.NettyCodecAdapter$InternalDecoder.messageReceived(NettyCodecAdapter.java:134)
	at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:80)
	at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
	at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559)
	at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:274)
	at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:261)
	at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:349)
	at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:280)
	at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:200)
	at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:44)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: com.alibaba.com.caucho.hessian.io.HessianProtocolException: expected integer at 0x24 [B ([B@1e919697)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.error(Hessian2Input.java:2720)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.expect(Hessian2Input.java:2691)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readInt(Hessian2Input.java:773)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readType(Hessian2Input.java:2296)
	at com.alibaba.com.caucho.hessian.io.BasicDeserializer.readObject(BasicDeserializer.java:251)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:1696)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer$ObjectFieldDeserializer.deserialize(JavaDeserializer.java:396)
	... 26 more

        看到这段异常,分分钟想到了dubbo序列化默认用的是hessian,而hessian处理复杂对象时爆出的异常,不太好理解,于是写出一个测试类模拟了一下hessian 序列化/反序列化

   

package com.apricotforest.casefolder.medical.utils;


import com.alibaba.com.caucho.hessian.io.HessianSerializerInput;
import com.alibaba.com.caucho.hessian.io.HessianSerializerOutput;
import com.apricotforest.casefolder.medical.search.vo.MedicalRecordSearchVo;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/**
 * Created by  on 16/5/31.
 */
public class HessianSerializeUtil {


    /**
     * 纯hessian序列化
     *
     * @param object
     * @return
     * @throws Exception
     */

    public static byte[] serialize(Object object) throws Exception {
        if (null == object) {
            throw new NullPointerException();
        }
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        HessianSerializerOutput hessianOutput = new HessianSerializerOutput(os);
        hessianOutput.writeObject(object);
        return os.toByteArray();
    }

    /**
     * 纯hessian反序列化
     *
     * @param bytes
     * @return
     * @throws Exception
     */

    public static Object deserialize(byte[] bytes) throws Exception {
        if (bytes == null) {
            throw new NullPointerException();
        }
        ByteArrayInputStream is = new ByteArrayInputStream(bytes);
        HessianSerializerInput hessianInput = new HessianSerializerInput(is);
        Object object = hessianInput.readObject();
        return object;
    }
    public static void main(String[] args) throws Exception {

        byte[] bytes;
        // String[] arr = {"6eb90e77-f37-4daf-8665-fc56951f9a25",
        //         "aedf9088-899c-4200-940e-72215b38d258","6142DD32-485A-4393-B757-24B8DC043E99"};

        String[] arr = new String[]{"4e2a6912-f4b9-4e04-a999-982ef2bcc64f", "88f4fcc6-43ef-4ccb-8a1a-d50d59313d3a"};
        MedicalRecordSearchVo searchVo = new MedicalRecordSearchVo()
                .setKeyword("ddd").setUserId(2100000005).setTagId(arr);
        bytes = HessianSerializeUtil.serialize(searchVo);
        System.out.println("序列化后对象:" + bytes);
        System.out.println("反序列化后正常属性: " + ((MedicalRecordSearchVo) HessianSerializeUtil.deserialize(bytes)).getKeyword());
        System.out.println("反序列号后数组属性: " + ((MedicalRecordSearchVo) HessianSerializeUtil.deserialize(bytes)).getTagId()[0]);

    }
}

       本地序列化后,发现数据可以正常反序列化,深入异常,查看异常所对应的代码块,调用栈如下

    

        仔细查看服务调用方传过来的数据,发现类型不匹配导致,升级依赖客户端即可

       

        ps:dubbo 接口联调过程,需要在本地联调,但是本地环境和开发环境共用一个zk,所以使用dubbo 控制台,对开发环境接口降权或添加白名单策略

猜你喜欢

转载自zhuanjiao520.iteye.com/blog/2302390