Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

com.alibaba.com.caucho.hessian.io.HessianProtocolException: com.alibaba.com.caucho.hessian.io.ObjectDeserializer: unexpected object java.lang.String (2) #45

Open
xuyanhua opened this issue Jun 27, 2018 · 2 comments

Comments

@xuyanhua
Copy link

我们使用dubbo的时候,返回的结果对象是这样的
class Result {
int code;//错误码
String message;//错误消息
T module ;//保存数据
}
但是调用时报反序列失败,报错如下:
Exception in thread "main" com.alibaba.com.caucho.hessian.io.HessianFieldException: AVX$Result.data: com.alibaba.com.caucho.hessian.io.ObjectDeserializer: unexpected object java.lang.String (2) at com.alibaba.com.caucho.hessian.io.JavaDeserializer.logDeserializeError(JavaDeserializer.java:163) at com.alibaba.com.caucho.hessian.io.JavaDeserializer$ObjectFieldDeserializer.deserialize(JavaDeserializer.java:394) at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:269) at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:196) at com.alibaba.com.caucho.hessian.io.SerializerFactory.readObject(SerializerFactory.java:527) at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2743) at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2683) at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2657) at AVX.deserialize(AVX.java:37) at AVX.main(AVX.java:18) Caused by: com.alibaba.com.caucho.hessian.io.HessianProtocolException: com.alibaba.com.caucho.hessian.io.ObjectDeserializer: unexpected object java.lang.String (2) at com.alibaba.com.caucho.hessian.io.AbstractDeserializer.error(AbstractDeserializer.java:101) at com.alibaba.com.caucho.hessian.io.AbstractDeserializer.readMap(AbstractDeserializer.java:90) at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2066) at com.alibaba.com.caucho.hessian.io.JavaDeserializer$ObjectFieldDeserializer.deserialize(JavaDeserializer.java:390) ... 8 more

代码如下:

`
import com.alibaba.com.caucho.hessian.io.Hessian2Input;
import com.alibaba.com.caucho.hessian.io.Hessian2Output;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;

public class AVX {
public static void main(String[] args) throws IOException, ClassNotFoundException {
HashMap<String, String> map = new HashMap<>();
map.put("2", "2");

    Result<HashMap<String, String>> test = new Result(map);
    byte[] bytes = serialize(test);

    Result<HashMap<String, String>> mm = (Result<HashMap<String, String>>) deserialize(bytes);
    System.out.println(mm);
}

public static byte[] serialize(Object obj) throws IOException {
    if (obj == null) throw new NullPointerException();

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    Hessian2Output ho = new Hessian2Output(os);
    ho.writeObject(obj);
    ho.flushBuffer();
    return os.toByteArray();
}

public static Object deserialize(byte[] by) throws IOException {
    if (by == null) throw new NullPointerException();

    ByteArrayInputStream is = new ByteArrayInputStream(by);
    Hessian2Input hi = new Hessian2Input(is);
    return hi.readObject();
}

static class Result<T extends Serializable> implements Serializable {

    public Result(T data) {
        this.data = data;
    }

    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "Result{" +
                "data=" + data +
                '}';
    }
}

}`

经过测试,如果
static class Result<T extends Serializable> implements Serializable {
改为
static class Result<T> implements Serializable {

则能正常反序列化出来。

求大神帮助 看看

@icankeep
Copy link

icankeep commented May 30, 2021

这个主要是因为T extends Serializable这样写之后,data字段的类型就是java.io.Serializable,在读取data字段的值的时候,就是通过readObject(in, java.io.Serializable.class)

最终就会执行到Hessian2Input#readObject(Class expectedClass, Class<?>... expectedTypes)中

  case 'H': {
      // 最终获取的是ObjectDeserializer
      Deserializer reader = findSerializerFactory().getDeserializer(expectedClass);

      boolean keyValuePair = expectedTypes != null && expectedTypes.length == 2;
      // ObjectDeserializer并没有实现readMap,所以最终调用的AbstractDeserializer#readMap,该方法最终都会抛出错误
      return reader.readMap(this
              , keyValuePair ? expectedTypes[0] : null
              , keyValuePair ? expectedTypes[1] : null);
  }

我不懂的是为啥这里是reader.readMap而不是reader.readObject,如果是readObject的话这个问题应该就不存在了

我觉得这应该是hessian2的bug

@justein
Copy link

justein commented May 31, 2021

如果不设计文件传输的场景,建议用其他的序列化方式把

@CrazyHZM CrazyHZM transferred this issue from apache/dubbo Oct 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants