关于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对象 ...
随机推荐
- Python3 print()函数sep,end,file参数用法练习
来自builtins.py:def print(self, *args, sep=' ', end='\n', file=None): # known special case of print &q ...
- jenkins创建构建任务
构建项目类型 点击 Jenkins 首页 “创建一个新任务” 的链接, 输入任务名称 Jenkins 提供了六种类型的任务. 构建一个自由风格的软件项目 这是Jenkins的主要功能.Jenkins ...
- .net core 多平台部署
首先下载地址 https://dotnet.microsoft.com/download 下载.net core 和 .net core runtime 然后安装他们 控制台运行项目: 找到你的工 ...
- Unix/Linux文件类型及访问权限
在Linux系统中,有7种文件类型. 普通文件 (regular file) 目录文件 (directory) 链接文件 (symbolic link) 管道文件 (FIFO) 套接字文件 (sock ...
- git基本操作若干
开发合并分支,推送到远程1. git diff 查看修改内容: . git add -A 添加所有修改: . git commit -am "给人的提示"; 提交修改内容 . gi ...
- Upgrading WebLogic Application Environments --官方文档
http://docs.oracle.com/cd/E13179_01/common/docs92/upgrade/dirstruct.html WebLogic Domain Directory S ...
- rails命令行命令
x.指定端口启动rails项目 ruby script/server webrick -p 3000 ------------------------------------------------- ...
- jQuery适用技巧笔记整合
1.关于页面元素的引用 通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用do ...
- CPU缓存一致性协议与java中的volatile关键字
有关缓存一致性协议MESI自行百度. 提出问题:volatile在缓存一致性协议上又做了哪些事情?为啥它不保证原子性? 在缓存一致性协议下,CPU为了执行效率使用了写(存储)缓存和失效队列从而导致对用 ...
- TextBox 控件
TextBox控件上有一个箭头,MultiLine属性,是多行显示 TextBox控件有System.Windows.TextBox类提供,提供了基本的文本输入和编辑功能 属性 A ...