`
lionheart
  • 浏览: 91118 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java序列化机制学习

阅读更多
什么是序列化
java中的序列化(serialization)机制能够将一个实例对象的状态信息写入到一个字节流中,使其可以通过socket进行传输、或者持久化存储到数据库或文件系统中;然后在需要的时候,可以根据字节流中的信息来重构一个相同的对象。序列化机制在java中有着广泛的应用,EJB、RMI等技术都是以此为基础的。

正确使用序列化机制
一般而言,要使得一个类可以序列化,只需简单实现java.io.Serializable接口即可。该接口是一个标记式接口,它本身不包含任何内容,实现了该接口则表示这个类准备支持序列化的功能。如下例定义了类Person,并声明其可以序列化。

public class Person implements java.io.Serializable {}


序列化机制是通过java.io.ObjectOutputStream类和java.io.ObjectInputStream类来实现的。在序列化(serialize)一个对象的时候,会先实例化一个ObjectOutputStream对象,然后调用其writeObject()方法;在反序列化(deserialize)的时候,则会实例化一个ObjectInputStream对象,然后调用其readObject()方法。下例说明了这一过程。
public void serializeObject(){
     String fileName = "ser.out";
     FileOutputStream fos = new FileOutputStream(fileName);
     ObjectOutputStream oos = new ObjectOutputStream(fos);
     oos.writeObject(new Person());
     oos.flush();
}

public void deserializeObject(){
     String fileName = "ser.out";
     FileInputStream fos = new FileInputStream(fileName);
     ObjectInputStream oos = new ObjectInputStream(fos);
     Person p = oos.readObject();
}

上例中我们对一个Person对象定义了序列化和反序列化的操作。但如果Person类是不能序列化的话,即对不能序列化的类进行序列化操作,则会抛出 java.io.NotSerializableException异常。
JVM中有一个预定义的序列化实现机制,即默认调用 ObjectOutputStream.defaultWriteObject()ObjectInputStream.defaultReadObject() 来执行序列化操作。如果想自定义序列化的实现,则必须在声明了可序列化的类中实现 writeObject()readObject()方法。

几种使用情况
一般在序列化一个类A的时候,有以下三种情况:
[list=3]
  • 类A没有父类,自己实现了Serializable接口
  • 类A有父类B,且父类实现了Serializable接口
  • 类A有父类B,但父类没有实现Serializable接口
  • [/list]
    对于第一种情况,直接实现Serializable接口即可。
    对于第二种情况,因为父类B已经实现了Serializable接口,故类A无需实现此接口;如果父类实现了writeObject()和readObject(),则使用此方法,否则直接使用默认的机制。
    对于第三种情况,则必须在类A中显示实现writeObject()和readObject()方法来处理父类B的状态信息;还有一点要特别注意,在父类B中一定要有一个无参的构造函数,这是因为在反序列化的过程中并不会使用声明为可序列化的类A的任何构造函数,而是会调用其没有申明为可序列化的父类B的无参构造函数。

    序列化机制的一些问题
    [list]
  • 性能问题
  • 为了序列化类A一个实例对象,所需保存的全部信息如下:
    1. 与此实例对象相关的全部类的元数据(metadata)信息;因为继承关系,类A的实例对象也是其任一父类的对象。因而,需要将整个继承链上的每一个类的元数据信息,按照从父到子的顺序依次保存起来。
    2. 类A的描述信息。此描述信息中可能包含有如下这些信息:类的版本ID(version ID)、表示是否自定义了序列化实现机制的标志、可序列化的属性的数目、每个属性的名字和值、及其可序列化的父类的描述信息。
    3. 将实例对象作为其每一个超类的实例对象,并将这些数据信息都保存起来。
    在RMI等远程调用的应用中,每调用一个方法,都需要传递如此多的信息量;久而久之,会对系统的性能照成很大的影响。
  • 版本信息
  • 当用readObject()方法读取一个序列化对象的byte流信息时,会从中得到所有相关类的描述信息以及示例对象的状态数据;然后将此描述信息与其本地要构造的类的描述信息进行比较,如果相同则会创建一个新的实例并恢复其状态,否则会抛出异常。这就是序列化对象的版本检测。JVM中默认的描述信息是使用一个长整型的哈希码(hashcode)值来表示,这个值与类的各个方面的信息有关,如类名、类修饰符、所实现的接口名、方法和构造函数的信息、属性的信息等。因而,一个类作一些微小的变动都有可能导致不同的哈希码值。例如开始对一个实例对象进行了序列化,接着对类增加了一个方法,或者更改了某个属性的名称,当再想根据序列化信息来重构以前那个对象的时候,此时两个类的版本信息已经不匹配,不可能再恢复此对象的状态了。要解决这个问题,可能在类中显示定义一个值,如下所示:
    private static final long serialVersionUID = ALongValue;
    

    这样,序列化机制会使用这个值来作为类的版本标识符,从而可以解决不兼容的问题。但是它却引入了一个新的问题,即使一个类作了实质性的改变,如增加或删除了一些可序列化的属性,在这种机制下仍然会认为这两个类是相等的。
    [/list]
    一种更好的选择
    作为实现Serializable接口的一种替代方案,实现java.io.Externalizable接口同样可以标识一个类为可序列化。
    Externalizable接口中定义了以下两个方法:
    public void readExternal(ObjectInput in);
    public void writeExternal(ObjectOutput out);
    

    这两个方法的功能与 readObject()和writeObject()方法相同,任何实现了Externalizable接口的类都需要这实现两个函数来定义其序列化机制。
    使用Externalizable比使用Serializable有着性能上的提高。前者序列化一个对象,所需保存的信息比后者要小,对于后者所需保存的第3个方面的信息,前者不需要访问每一个父类并使其保存相关的状态信息,而只需简单地调用类中实现的writeExternal()方法即可。
    分享到:
    评论
    1 楼 hanmiao 2012-12-04  
    楼主,你所说的"在声明了可序列化的类中实现 writeObject() 和 readObject() 方法",是不是就像下面这样:
    public class Person implements java.io.Serializable {
    	public final void writeObject(Object obj) throws IOException {
    		//...
    	}
    	
    	public final Object readObject() throws IOException, ClassNotFoundException {
    		//...
    	}
    }

    相关推荐

      Java 反序列化学习的实验代码.rar

      Java反序列化漏洞学习实践中的代码 Java反序列化漏洞学习实践一:从Serializbale接口开始,...Java反序列化漏洞学习实践二:Java的反射机制(Java Reflection) Java反序列化漏洞学习实践三:理解java的动态代理机制

      通过实例了解java序列化机制

      主要介绍了通过实例了解java序列化机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

      深入理解Java原生的序列化机制

      Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。下面小编和大家来一起学习一下吧

      【Java面试+Java学习指南】 一份涵盖大部分Java程序员所需要掌握的核心知识

      序列化和反序列化 继承、封装、多态的实现原理 容器 Java集合类总结 Java集合详解1:一文读懂ArrayList,Vector与Stack使用方法和实现原理 Java集合详解2:Queue和LinkedList Java集合详解3:Iterator,fail-fast机制...

      java基础学习笔记之java oop高级java异常处理机制、集合、文件操作、序列化与反序列化、字符串处理(三)

      JAVA异常处理机制 一、什么异常(Exception) 1.生活中异常:不正常事件(意外) 2.程序异常:异常是指在程序的运行过程中所发生的不 正常的事件(例外,错误),它会中断正在运行的程序。 3.什么是异常处理:java编程语言使用...

      动力节点老杜推荐Java学习路线

      学习Java的IO编程,包括文件读写、网络编程和序列化等。 阶段三:Web开发与框架 学习JavaWeb开发的基础知识,包括Servlet、JSP和JDBC等,了解MVC模式。 学习常用的JavaWeb框架,如Spring和Spring MVC,了解依赖注入...

      「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识 准备 Java 面试,首选.zip

      Java 序列化详解 泛型&通配符详解 Java 反射机制详解 Java 代理模式详解 BigDecimal 详解 Java 魔法类 Unsafe 详解 Java SPI 机制详解 Java 语法糖详解 集合 知识点/面试题总结 : Java 集合常见知识点&面试题总结...

      「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识

      Java 序列化详解 泛型&通配符详解 Java 反射机制详解 Java 代理模式详解 BigDecimal 详解 Java 魔法类 Unsafe 详解 Java SPI 机制详解 Java 语法糖详解 集合 知识点/面试题总结: Java 集合常见知识点&面试题总结...

      JAVA上百实例源码以及开源项目源代码

       Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

      Java开发技术大全(500个源代码).

      Student.java 定义一个用来序列化的类 ThreadIn.java 接收数据用的线程类 ThreadOut.java 发送数据用的线程类 TypeFile.java 显示文件内容的类 useScanner.java 用Scanner接收用户的输入 第8章 示例描述:本章...

      Java工程师面试复习指南

      序列化和反序列化 继承封装多态的实现原理 集合类 Java集合类总结 Java集合详解:一文读懂ArrayList,Vector与Stack使用方法和实现原理 Java集合详解:Queue和LinkedList Java集合详解:迭代器,快速失败机制与比较器...

      【白雪红叶】JAVA学习技术栈梳理思维导图.xmind

      序列化 nIo 匿名类 包装类 优先级 引用 语言工具类库 容器类 集合 链表 map 工具类 系统类 日期类 数字类 字符串+正则 流 字符流 字节流 语言特性 继承 封装 多态 JVM 多线程与并发 GC...

      java源码包---java 源码 大量 实例

       Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

      JAVA上百实例源码以及开源项目

       Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

      JAVA基础课程讲义

      JAVA对象的序列化和反序列化 161 为什么需要序列化和反序列化 161 对象的序列化主要有两种用途 161 序列化涉及的类和接口 162 序列化/反序列化的步骤和实例 162 综合的序列化和反序列化练习 163 JAVA.IO包相关流对象...

      java常用类解析及示例及一些工具类源代码

      主要讲解了System类、Object类、Arrays类、Cloneable接口、IO系统输入输出类及装饰类、IO系统文本读写工具类、IO系统二进制读写工具类、对象序列化工具类、File类及文件搜索工具类、java异常机制及自定义异常类、...

      Java思维导图xmind文件+导出图片

      理解通信协议传输过程中的序列化和反序列化机制 基于框架的RPC通信技术 WebService/ApacheCXF RMI/Spring RMI Hession 传统RPC技术在大型分布式架构下面临的问题 分布式架构下的RPC解决方案 Zookeeper ...

      java源码包4

       Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

      IPCDemo:Android IPC 机制学习 AIDL Messenger 通讯方式

      Android 序列化机制在 Android 系统中关于序列化的方法一般有两种,分别是实现 Serializable 接口和 Parcelable 接口Serializable 是来自 Java 中的序列化接口Parcelable 是 Android 自带的序列化接口上述的两种序列...

      java源码包3

       Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...

    Global site tag (gtag.js) - Google Analytics