专栏首页Java后端技术栈cwnait面向对象--序列化与反序列化

面向对象--序列化与反序列化

概述

内存中的数据对象只有转换成二进制才可以进行数据持久化和网络传输。将数据对象转换成二进制的流程称之为对象的序列化(Serialization)。

反之,将二进制流恢复为数据对象的过程称之为反序列化(Deserialization)。序列化需要保留充分的信息以恢复数据对象,但是为了节省存储空间和网络带宽,序列化后的二进制流又要尽可能的小。序列化常见的使用时RPC框架的数据传输。

常见三种序列化方式

Java原生序列化

Java类型通过实现Serializable接口来实现该类对象的序列化,这个接口非常特殊,没有任何方法,只是起到一个标识符的作用。Java序列化保留了对象的元数据(如类、成员变量、继承类信息等),以及对象数据等,兼容性最好,但是不支持跨语言,同时性能不是最好的。

实现Serializable接口的类建议设置serialVersionUID字段值,如果不设置,那么每次运行时,编译器会根据类的内部实现,包括类名、接口名、方法名和属性等来自动生成serialVersionUID。如果类的源代码有修改,那么重新编译后serialVersionUID的取值可能会变化。因此实现Serializable接口的类最好是显示低设置serialVersionUID值,修改类时候可以根据需要或者兼容性来决定是否需要修改serialVersionUID值。

SerialVersionUID是一个标识符,当它通常使用对象的哈希码序列化时会标记在对象上。我们可以通过Java中serialver工具找到该对象的serialVersionUID。

  • 如果是兼容升级,请不要修改serialVersionUID字段,避免反序列化失败 java.io.NotSerializableException。
  • 如果是不兼容升级,需要修改serialVersionUID值,避免反序列化失败java.io.NotSerializableException。

使用Java原生态序列化需要注意,Java反序列化时候不会调用类的无参构造方法,而是调用native方法将成员变量赋值为对应类型的初始值,基于性能以及兼容性的考虑,不推荐使用Java序列化。

Hessian序列化

Hessian序列化是一种支持动态类型、跨语言、即将于对象传输的网络协议。Java对象序列化的二进制流可以被其他语言(如:C++,python等语言)反序列化。

特性:

自描述序列化类型,不依赖外部描述文件或接口定义,用一个字节表示常用基础类型,极大的缩短了二进制流。

  • 语言无关性,支持脚本语言
  • 协议简单,比Java原生态序列化高效

相比Hessian 1.0、Hessian 2.0中增加了压缩编码,其序列化二进制流大小是Java原生态序列化的50%,序列化耗时是Java原生态大小的30%,反序列化耗时是Java原生态反序列化的20%。

Hessian 会把复杂对象所有属性存储在一个map中进行序列化。所以在父类、子类存在同名成员变量的情况下,Hessian 序列化时,先序列化子类,然后序列化父类,因此反序列化结果会导致子类同名成员变量被父类的值覆盖。

JSON序列化

JSON序列化这里的JSON=JavaScript Object Notation,是一种轻量级的数据交换格式,JSON 序列化就是将数据对象转换成JSON字符串。在序列化过程中跑起来类型信息,所以反序列化时候只有提供类型信息才能准确低反序列化。相比前面两种方式JSON可读性笔记好,方便调试。

序列化通常会通过网络协议传输对象,而对象中往往有敏感数据,所以序列化常常是黑客们的攻击点,攻击者穷秒地利用反序列化过程构造恶意代码,是得程序在反序列化过程中执行任意代码。

Java工程中广泛使用的Apache Commons Collections、Jackson、fastjson等都出现过反序列化漏洞。

如果防范这种黑客攻击呢?

将一些对象的敏感信息不进行序列化传输,可以加关键字transient修饰,避免把该属性信息转化为序列化的二进制流。如果一定要传递对象的敏感信息,也可以使用对称加密和非对称加密方式独立传输,再使用某个方法把属性还原丹对象中。transient 修饰符仅适用于变量,不适用于方法和类。在序列化时,如果我们不想序列化特定变量以满足安全约束,那么我们应该将该变量声明为transient。执行序列化时,JVM会忽略transient变量的原始值并将默认值保存到文件中。因此,transient意味着不要序列化。

应用开发者对序列化要有一定的安全意识防范,对传入数据的内容进行校验或者权限控制,及时更新安全漏洞,避免遭到黑客攻击。

本文分享自微信公众号 - Java后端技术栈(t-j20120622),作者:lawt

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java序列化连环炮:是什么?为什么需要?如何实现?

    遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题

    用户4143945
  • Spring+Dubbo+Zookeeper简单框架与使用

    1、搭建框架前先下载Zookeeper(http://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.3.6/zoo...

    用户4143945
  • 如何搞定Mybatis 中的 9 种设计模式

    虽然我们都知道有很多设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深...

    用户4143945
  • 【问底】静行:FastJSON实现详解

    还记得电影《功夫》中火云邪神的一句话:天下功夫,无坚不破,唯快不破。在程序员的世界中,“快”一直是大家苦苦修炼,竞相追逐的终极目标之一,甚至到了“不择手段”、“...

    CSDN技术头条
  • Java序列化连环炮:是什么?为什么需要?如何实现?

    遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题

    用户4143945
  • Java序列化 3 连问

    Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程:

    xcbeyond
  • Java 序列化机制

    1、一般情况下,只有当 JVM 处于运行时,Java 对象才可能存在,即这些对象的生命周期不会比 JVM 的生命周期更长。但在现实应用中,就可能要求在 JVM ...

    JMCui
  • 数据序列化的那些事

    为什么需要数据序列化呢?因为数据要“传输”,比如将数据网络通信传递给其他服务器,或者持久化到磁盘。那么传输为什么需要序列化呢?因为在内存中的数据,当前进程是知道...

    luoxn28
  • Python学习笔记 --- 序列化Serialization

    序列化 (serialization) 序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,

    用户2398817
  • 夯实Java基础系列22:一文读懂Java序列化和反序列化

    本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看

    Java技术江湖

扫码关注云+社区

领取腾讯云代金券