dubbo传递对象时,发送端和接受端对象serialVersionUID不一致会如何?

标签: Serializable
41人阅读 评论(0) 收藏 举报
分类:

最近在做一个dubbo接口的时候,突然想到如果将发送对象的serialVersionUID改成和接受对象的serialVersionUID不一致时,会不会导致反序列化失败?

都知道在java的序列化和反序列化里面,如果传输对象的serialVersionUID前后不一致,用java序列化和反序列化时会报错。
java.io.InvalidClassException:stream classdesc serialVersionUID = 6457272772, local class serialVersionUID = -1923645274767028479 (可以查询java中serialVersionUID 的作用)

但是,在实际的dubbo接口测试过程中,特意更改了传输对象的前后的serialVersionUID,结果是依然可以成功的接受对象,即成功的序列化和反序列化

为什么?
开始困扰了好久,后来偶然看到一句话,“hessian2序列化:hessian是一种跨语言的高效二进制序列化方式。但这里实际不是原生的hessian2序列化,而是阿里修改过的hessian lite,它是dubbo RPC默认启用的序列化方式。”。后来就想,是不是因为序列化方式有关,会不会是Hessian序列化时并不会在意serialVersionUID的变化。

为证实心中的疑虑。分别采用了Hessian和java两种序列化方式进行验证。

这里有2个工程,一个发送端,一个接收端,采用SpringBoot启动,两个工程里面都分别载入了实体对象Person。用于测试对象serialVersionUID相同和不相同的情况。

1.第一个工程,是传输对象接受端,这里反序列化。serializabletest-server。3个主类
1.1.Person.java 传输对象。

@ToString
@Data
public class Person implements Serializable {

    private static final long serialVersionUID = -1923645274767028479L;

    private String[] address;

    private String name;

    private int phone;

}

1.2. HessianController.java hessian反序列化接受类。通过一个Controller接受http提交过来的对象信息


@Slf4j
@RestController
@RequestMapping("/hessian")
public class HessianController {

    @RequestMapping(value = "/hello")
    public String helloWorld(HttpServletRequest request, HttpServletResponse response) throws IOException {
        log.info("hessian反序列化开始------------------------");
        ServletInputStream sis = request.getInputStream();
        Hessian2Input h2i = new Hessian2Input(sis);
        h2i.startMessage();
        Person person = (Person) h2i.readObject();
        h2i.completeMessage();
        h2i.close();
        sis.close();
        log.info("hessian反序列化结果"+person.toString());
        return person.toString();
    }
}

1.3 JavaController.java Java反序列化接受类,通过一个Controller接受http提交过来的对象信息

@Slf4j
@RestController
@RequestMapping("/java")
public class JavaController {

    @RequestMapping(value = "/seri")
    public String helloWorld(HttpServletRequest request, HttpServletResponse response) throws Exception {

        log.info("java反序列化开始------------------------");
        ServletInputStream sis = request.getInputStream();
        ObjectInputStream is = new ObjectInputStream(sis);
        Person person = (Person) is.readObject();
        log.info("java"+person.toString());
        return person.toString();
    }
}

2、第二个工程,是传输对象发送端,这里进行对象序列化,并post发送请求。serializabletest-client。也是3个主类
2.1 Person.java


@ToString
@Data
public class Person implements Serializable {

    //通过变更serialVersionUID,分别测试与serializabletest-server中相同和不同的情况
    private static final long serialVersionUID = 6457272772L;

    private String[] address;

    private String name;

    private int phone;

}

2.2 HessianTest.java Hessian序列化对象 并发送

public class HessianTest {

    public static String urlName = "http://localhost:8080/hessian/hello";

    public static void main(String[] args) throws Throwable {

        // 序列化
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        Hessian2Output h2o = new Hessian2Output(os);
        h2o.startMessage();
        h2o.writeObject(getPerson());
        h2o.writeString("I am client.");
        h2o.completeMessage();
        h2o.close();

        byte[] buffer = os.toByteArray();
        os.close();
        ByteArrayEntity byteArrayEntity = new ByteArrayEntity(buffer,
                ContentType.create("x-application/hessian", "UTF-8"));

        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(urlName);
        post.setEntity(byteArrayEntity);
        CloseableHttpResponse response = client.execute(post);

        System.out.println("response status:\n"
                + response.getStatusLine().getStatusCode());
        HttpEntity body = response.getEntity();
        System.out.println("body:"+body);
    }

    public static Person getPerson() {
        Person person = new Person();
        person.setAddress(new String[] { "Beijing", "TaiWan", "GuangZhou" });
        person.setName("Jack");
        person.setPhone(188888888);
        return person;
    }

2.3 JavaTest.java java序列化并发送

public class JavaTest {

    public static String urlName = "http://localhost:8080/java/seri";

    public static void main(String[] args) throws Throwable {


        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream os = new ObjectOutputStream(bos);
        os.writeObject(getPerson());
        byte[] buffer = bos.toByteArray();
        os.close();
        ByteArrayEntity byteArrayEntity = new ByteArrayEntity(buffer,
                ContentType.create("x-java-serialized-object", "UTF-8"));

        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(urlName);
        post.setEntity(byteArrayEntity);
        CloseableHttpResponse response = client.execute(post);

        System.out.println("response status:\n"
                + response.getStatusLine().getStatusCode());
        HttpEntity body = response.getEntity();
        System.out.println("body:"+body);
    }

    public static Person getPerson() {
        Person person = new Person();
        person.setAddress(new String[] { "Beijing", "TaiWan", "GuangZhou" });
        person.setName("Jack");
        person.setPhone(188888888);
        return person;
    }

}

3.测试:
这里分两种情况测试
3.1*测试第一种情况*
我们将发送端(serializabletest-client)中的person对象的serialVersionUID保持与serializabletest-server端一致,即将2.1中的serialVersionUID改为-1923645274767028479L 保持跟1.1一致。
分别运行HessianTest.java 和 JavaTest.java 得到serializabletest-server服务端中日志 如下
这里写图片描述

结论:当传输对象的serialVersionUID前后,这里两种方式Hessian和java都能成功序列化和反序列化操作

3.2*测试第二种情况*
将发送端和接受的端的serialVersionUID改为不一致。例,将2.1中的serialVersionUID改为6457272772L,1.1保持原来的值不变。 分别运行HessianTest.java 和 JavaTest.java 得到serializabletest-server服务端中日志 如下

这里写图片描述

结论:这里可以看到,在传输对象的serialVersionUID前后不一致时候,Hessian可以成功进行“反序列化”操作。但是java方式不能进行“反序列化”。

查看评论

java 序列化 serialVersionUID transient

为什么要序列化? 我们所说的序列化是“对象状态”的序列化,将对象转化为流的过程就是序列化;从流恢复为对象的过程就是反序列化;序列化的都是对象的状态,所以静态字段不会被序列化。 序列化的应用场景 1...
  • wangjun5159
  • wangjun5159
  • 2015-11-19 22:31:23
  • 667

JFinal学习心得

JFinalJFinal基本配置内置Jetty启动项目:Jfinal推荐使用WebRoot\WEB-INF\classes放class文件, 于是创建项目的时候Default output fold...
  • dartagnan_wang
  • dartagnan_wang
  • 2015-10-07 01:26:19
  • 7502

java类中serialversionuid 作用 是什么?举个例子说明

serialVersionUID适用于Java的序列化机制。简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的...
  • suchahaerkang
  • suchahaerkang
  • 2017-12-05 17:34:28
  • 82

Dubbo各种协议

原文地址:http://dubbo.io/User+Guide-zh.htm#UserGuide-zh-协议参考手册 协议参考手册 (+) (#) 推荐使用Dubbo协议 ...
  • tanga842428
  • tanga842428
  • 2016-10-01 14:44:54
  • 38960

java匿名类序列化问题

java不同语法的应用在duboo服务中产生诡异的序列化错误,两种语法表达,一个无法序列化而另外一个正常...
  • xqj198404
  • xqj198404
  • 2017-10-18 12:23:43
  • 325

serialVersionUID的作用

在版本升级时反序列化(就是将一连串字节重建对象的时候)仍保持对象的唯一性。保持统一的一种方式。Java的序列化机制Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化de...
  • zm19936
  • zm19936
  • 2016-02-25 09:38:54
  • 92

JFinal开发Demo

这几天研究了一下JFinal,不得不说,开发速度真快,而且简单易使用。
  • Java__Coder
  • Java__Coder
  • 2015-12-11 23:12:50
  • 4607

dubbo源码分析-consumer端6-数据发送与接收

consumer端的数据经过处理后,最终进入发送的流程。接下来我们继续跟着数据的流向进行分析。 首先进入到了DubboInvoker,DubboInvoker中包含了多个ExchangeClient,...
  • youaremoon
  • youaremoon
  • 2016-07-07 00:28:58
  • 2341

消息队列activemq整合spring发送端和接收端配置

发送端的配置 目标连接 工厂 模板 队列目的地.....主题目的地 --> 接收端的配置,接收端是通过监听器实...
  • ha2015
  • ha2015
  • 2017-06-23 21:47:25
  • 147

【shiro】--- 集成web

第一步:建立一个maven web项目,引入jar包:                javax.servlet       javax.servlet-api     ...
  • u013045959
  • u013045959
  • 2017-08-28 21:09:57
  • 201
    个人资料
    等级:
    访问量: 12万+
    积分: 1581
    排名: 3万+
    最新评论