关于serialVersionUID与序列化"
java序列化trick and trap
厂内经常出现序列化对象版本不匹配问题,于是发本文说明一些序列化的注意点
调用MQ、memcached、rpc等等涉及到远程通讯的都会经过序列化,虽然客户端透明的封装了细节,但底层是一定会有序列化操作的。因此了解序列化的注意事项是非常有必要的,可以避免误用导致潜在的风险
通过网络传输的对象,必须实现Serializable接口,或者父类已经实现序列化接口。
网络传输对象继承层次不宜过深,封装在内部的对象也不宜太复杂。(太复杂很容易出现某个相关的类没实现序列化接口,而导致整个对象无法序列化)
- 一般long/int/String/Map/List/Array等常见类组成的对象就 能解决问题
- 最好不要在本应用对外的业务接口中传递或返回“由另一人或系统主导的业务对象"。因为你不能保证别人的对象版本会兼容,从而导致错误扩散
在接口定义上用的是父类,实际远程传输过去的是子类,反序列化不了的。特别是在rpc中客户端容易出现此问题
远程接口上的参数、返回值类型、会抛出的异常类,都要实现序列化接口。并且server和client都要有对应的类。
- 一个比较容易忽略的例子是:某服务接口可能会抛出某个运行时异常,但没有把这个异常类放入客户端中,一旦抛出此异常,客户端接收到此异常就会无法反序列化
ArrayList.subList()返回的List实现类是内部类型,不能序列化的,通过网络传输会出错。
ArrayList经过网络传输后,里面的元素顺序可能不一样
网络传输对象要有无参构造器(如果定义了有参构造器那就要显式定义一个无参构造起),因为机器是不知道传什么内容给有参构造器进行实例化,无参构造器不是public都没关系。没定义无参构造器,有些序列化方式会在底下生成无参构造器的方式才能解决问题。
网络传输最好不要用enum类型,太强耦合,从网络一端传到另一端,对方可能还是旧版本而识别不了。
- Enum 常量的序列化不同于普通的 serializable 或 externalizable 对象。enum 常量的序列化形式只包含其名称;常量的字段值不被传送。为了序列化 enum 常量,ObjectOutputStream 需要写入由常量的名称方法返回的字符串。
不需通过网络传输的field用transient定义,但有些json序列化类库是不会区别对待这种field
有些序列化类库,遇到反序列化不了的类,会反序列化成Map,但会在使用时遇到class cast异常。
同一应用不要有同package同名的类,可能隐藏在同名/不同名/不同版本的jar中。
serialVersionUID
用于网络传输的对象,第一次上线使用时,就一定要设定serialVersionUID,不要不顾编译警告
NOTE: 网络对象的匹配,除了靠类名,还靠serialVersionUID,serialVersionUID在《Java语言规范》有固定算法,跟各field的定义相关,如果没有显式赋值,虽然看不见,但会底下会默认算出一个进行网络传输。
如果没有显式赋值,在看不见觉察不到的情况下,在你增减了field/修改了定义的情况下,serialVersionUID已被改变,这时网络两端就对接不上而悲剧了。
没定义serialVersionUID,而又发生了serialVersionUID变化,网络两端只有所有机器都停掉,并且先后起有顺序时,才能不出丝毫差错。
最好不要用用1L作为serialVersionUID。0L对于java enum的序列化有特殊意义。
没赋值serialVersionUID 只是警告,不是错误,造成没设定serialVersionUID,网络两端上线运行一段时间也感觉正常。如果再增减修改field,没赋值好serialVersionUID,网络两端就不匹配。
- 算出旧版本的serialVersionUID(使用serialver或eclipse),设置到新版本的代码中
本文大部分内容取自前同事的分享资料,作了少许修改,外网地址
更多精彩内容请访问首发博客http://jenwang.me
进一步交流:
- Email:jenwang@foxmail.com
- 对于本博客某些话题感兴趣,希望进一步交流的,请加 qq 群:2825967
- 更多技术交流分享在圈子「架构杂谈」,跟老司机们聊聊互联网前沿技术、架构、工具、解决方案等
关于serialVersionUID与序列化"的更多相关文章
- java 序列化 serialVersionUID 的作用 和 两种添加方式
serialVersionUID适用于Java的序列化机制.简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的 ...
- Java 基础 - java序列化 & serialVersionUID
ref: https://www.cnblogs.com/duanxz/p/3511695.html ------------------- SerialVersionUID概述 SerialVers ...
- 一文看懂Java序列化之serialVersionUID
serialVersionUID适用于Java的序列化机制.简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的 ...
- serialVersionUID序列化版本号与ObjectOutputStream对象输入输出流
1. 观察ObjectOutputStream 我们观察ObjectOutputStream就可以发现该类没有无参构造,只有有参构造,所以他是一个包装流 2. 具体使用: public static ...
- 序列化之serialVersionUID
serialVersionUID作用: 序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性. 序列化ID起着关键的作用,java的序列化机制是通过在运行时判断类的serialVer ...
- Java中的序列化Serialable高级详解
来自[http://blog.csdn.net/jiangwei0910410003/article/details/18989711] 引言 将 Java 对象序列化为二进制文件的 Java 序列化 ...
- Java的序列化ID的作用
Java的序列化ID的作用 简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的serialVersio ...
- 黑马程序员_Java基础:序列化(Serializable)与反序列化
------- android培训.java培训.期待与您交流! ---------- 在学习IO中的ObjectOutputStream和ObjectInputStream时,会涉及到序列化和反序列 ...
- Java序列化的几种方式以及序列化的作用
Java序列化的几种方式以及序列化的作用 本文着重讲解一下Java序列化的相关内容. 如果对Java序列化感兴趣的同学可以研究一下. 一.Java序列化的作用 有的时候我们想要把一个Java对象 ...
随机推荐
- hibernate_SessionFactory_getCurrentSession_JTA简介
JTA:java transaction api java里所规定的一种管理事务的API 在另一篇播客我写到了,SessionFactory需要关注两个方法, 即: openSession ...
- Linux 命令学习之cd
功能说明: cd 命令是 linux 最基本的命令语句,其他的命令都会依赖与 cd 命令.因此学好 cd 命令是必须的. 语 法:cd [目的目录] 补充说明:cd指令可让用户在不同的目录间切换,需要 ...
- Java 中 String 的常用方法(一)
上一篇介绍了 String 中的几个常用构造方法,由 String 这个核心对象发散出去关于字符的编码,字符的字节表达,对 GC 的影响,正则表达式,模式匹配,这可能是 Java 里内涵最丰富的对象了 ...
- 公司Git实用记录
一.git命令名词解释 1.添加/跟踪/暂存:添加到本地索引 git add 文件名 2.提交:提交到本地仓库 git commit -m '注释' 3.推送:将提交到本地仓库的所有更新提交到服务器 ...
- php 析构函数,构造函数
php 析构函数,构造函数 <?php /** * 测试使用的PHP操作类 * Date: 2017/7/13 * Time: 14:22 */class Test{ /** 姓名 */ p ...
- JavaScript函数——闭包
闭包 概念 只有函数内部的子函数才能读取局部变量,所以闭包可以理解成"定义在一个函数内部的函数".在本质上,闭包是将函数内部和函数外部连接起来的桥梁 例子 function out ...
- (一)JNI基本概念
1. 基本概念: 首先,注意:C和C++在调用JNI时候方法是不一样的 注意看下面两个的区别: C++ #include <jni.h> #include <string> e ...
- Java包装类、拆箱和装箱详解
转载:https://www.cnblogs.com/ok932343846/p/6749488.html 虽然 Java 语言是典型的面向对象编程语言,但其中的八种基本数据类型并不支持面向对象编程, ...
- Java注解拾遗
注解简介: 注解Annotation是jdk1.5的新增功能,在现在的日常开发中,几乎离不开注解,写篇短文,来做个拾遗. 注解作用: Annotation(注解)的作用是修饰包.类.构造方法.方法.成 ...
- BZOJ1031 [JSOI2007]字符加密
Description 喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法 :把需要加密的信息排成一圈,显然,它们有很多种不同的读法.例如下图,可以读作 ...