`

java序列化 ---- 2016-07-30

    博客分类:
  • java
 
阅读更多

serialVersionUID的作用

 

serialVersionUID的作用

简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)

serialVersionUID有两种显示的生成方式:        一个是默认的1L,比如:private static final long serialVersionUID = 1L;        一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:        private static final   long     serialVersionUID = xxxxL; 当你一个类实现了Serializable接口,如果没有显示的定义serialVersionUID,Eclipse会提供这个      提示功能告诉你去定义 。在Eclipse中点击类中warning的图标一下,Eclipse就会      自动给定两种生成的方式。如果不想定义它,在Eclipse的设置中也       可以把它关掉的,设置如下:         Window ==> Preferences ==> Java ==> Compiler ==> Error/Warnings ==>         Potential programming problems         将Serializable class without serialVersionUID的warning改成ignore即可。
当实现java.io.Serializable接口的实体(类)没有显式地定义一个名为serialVersionUID,类型为long的变量时,Java序列化机制会根据编译的class(它通过类名,方法名等诸多因素经过计算而得,理论上是一一映射的关系,也就是唯一的)自动生成一个serialVersionUID作序列化版本比较用,这种情况下,如果class文件(类名,方法明等)没有发生变化(增加空格,换行,增加注释,等等),就算再编译多次,serialVersionUID也不会变化的.

如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,未作更改的类,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。

如果你没有考虑到兼容性问题时,就把它关掉,不过有这个功能是好的,只要任何类别实现了Serializable这个接口的话,如果没有加入 serialVersionUID,Eclipse都会给你warning提示,这个serialVersionUID为了让该类别 Serializable向后兼容。

问题一:假设有A端和B端,如果2处的serialVersionUID不一致,会产生什么错误呢?

问题二:假设2处serialVersionUID一致,如果A端增加一个字段,B端不变,会是什么情况呢?

问题三:假设2处serialVersionUID一致,如果B段增加一个字段,A端不变,会是什么情况呢?

问题四:假设2处serialVersionUID一致,如果A端减少一个字段,B端不变,会是什么情况呢?

问题五:假设2处serialVersionUID一致,如果B端减少一个字段,A端不变,会是什么情况呢?

 

例子如下:写2个类,类名相同,字段相同,方法相同.放在不同的包里,来模仿A端和B端.

实体类:在本例中,在测试类SerialTest执行前代表A端,然后,在测试类DeserialTest执行前代表B端.

package com.test; import java.io.Serializable;

public class Serial implements Serializable{ /**   *   */ private static final long serialVersionUID = 6977402643848374753L; int id;       String name;       public Serial(int id, String name) {           this.id = id;           this.name = name;       }       public String toString() {           return "DATA: " + id + " " +name;         }   }

 

测试类,代表A端的序列化

import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectOutputStream;
public class SerialTest {
/**   * @param args   */ 
	public static void main(String[] args) {   
		// TODO Auto-generated method stub   
		Serial serial1 = new Serial(1,"song");  
		System.out.println("Object Serial"+serial1);     
		try {    
			FileOutputStream fos = new FileOutputStream("serialTest.txt");    
			ObjectOutputStream oos = new ObjectOutputStream(fos);    
			oos.writeObject(serial1);    
			oos.flush();    
			oos.close();         
		} catch (Exception e) {    
				// TODO Auto-generated catch block    
				e.printStackTrace();   
		}
	}
}





import java.io.FileInputStream; 
import java.io.FileNotFoundException;
import java.io.IOException; 
import java.io.ObjectInputStream;
public class DeserialTest {
/**   * @param args   */ 
	public static void main(String[] args) {   
		// TODO Auto-generated method stub   
		Serial serial2 ;   
		try {    
			FileInputStream fis = new FileInputStream("serialTest.txt");    
			ObjectInputStream ois = new ObjectInputStream(fis);    
			serial2 = (Serial)ois.readObject();    
			ois.close();    
			System.out.println("Object Deserial"+serial2);   
		} catch (Exception e) {    
			// TODO Auto-generated catch block    
			e.printStackTrace(); 
		}
	}
}

 

问题一:假设有A端和B端,如果2处的serialVersionUID不一致,会产生什么错误呢?

答案如下:

1)先执行测试类SerialTest,然后修改serialVersion值(或注释掉serialVersion并编译),再执行测试类DeserialTest,报错:

java.io.InvalidClassException: com.test.serializable.Serial; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 11

2)A端和B端都没显示的写serialVersionUID,实体类没有改动(如果class文件(类名,方法明等)没有发生变化(增加空格,换行,增加注释,等等),).序列化,反序列化正常.

 

问题二:假设2处serialVersionUID一致,如果A端增加一个字段,B端不变,会是什么情况呢?

答案二: 序列化,反序列化正常,A端增加的字段丢失(被B端忽略).

问题五:假设2处serialVersionUID一致,如果B端减少一个字段,A端不变,会是什么情况呢?

答案:与问题二类似,序列化,反序列化正常,B端字段少于A端,A端多的字段值丢失(被B端忽略).

 

问题三:假设2处serialVersionUID一致,如果B段增加一个字段,A端不变,会是什么情况呢?

问题四:假设2处serialVersionUID一致,如果A端减少一个字段,B端不变,会是什么情况呢?(与问题三类似,四答案:序列化,反序列化正常,B端字段多余A端,B端多出的字段被赋予对应类型的默认值)

答案三: 序列化,反序列化正常,B端新增加的int字段被赋予了默认值0.  

例子如下:

3)先执行SerialTest,然后在实体类增加一个字段age,再执行测试类DeserialTest.

import java.io.Serializable;

public class Serial implements Serializable{
	
	int id;
	String name;
	public int age ;
    public Serial(int id, String name) {           
    	this.id = id;           
    	this.name = name;       
    }       
    public String toString() {           
    	return "DATA: " + id + " " +name;         
    }     
}


import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class DeserialTest {
/**   * @param args   */ 
	public static void main(String[] args) {   
	// TODO Auto-generated method stub   
		Serial serial2 ;   
		try { 
			File file = new File("serialTest.txt");
			if(!file.exists())
				file.createNewFile();
			FileInputStream fis = new FileInputStream(file);    
			ObjectInputStream ois = new ObjectInputStream(fis);    
			serial2 = (Serial)ois.readObject();    
			ois.close();    
			System.out.println("Object Deserial"+serial2+" age="+serial2.age);   
		}catch (Exception e) {    
			// TODO Auto-generated catch block    
			e.printStackTrace();   
		}
	}
}

 

打印结果如下:

Object DeserialDATA: 1 song age=0

说明序列化,反序列化正常,B端新增加的int字段被赋予了默认值0.

 

上面的情况对增加/减少 字段/方法 都适用.

//但当serialVersionUID相同时,它就会将不一样的field以type的预设值Deserialize,可避开不兼容性问题。

原文地址:http://www.cnblogs.com/guanghuiqq/archive/2012/07/18/2597036.html

 

分享到:
评论

相关推荐

    Java序列化

    Java序列化是Java平台中的一种标准机制,允许将对象的状态转换为字节流,以便存储在磁盘上、通过网络进行传输或者在某些时候恢复原来的对象状态。这一过程包括两个主要步骤:对象的序列化(将对象转换为字节流)和反...

    Protocol Buffer序列化对比Java序列化.

    【Protocol Buffer序列化对比Java序列化】 Protocol Buffer(简称PB)是Google开发的一种高效的数据序列化协议,而Java序列化是Java平台内置的一种序列化机制。两者的主要目标都是将对象转化为字节数组,便于在网络...

    java 序列化时排除指定属性

    Java序列化是Java平台提供的一种持久化机制,它允许我们将一个Java对象转换为字节流,以便存储到磁盘上,或者通过网络进行传输。这使得我们可以保存和恢复对象的状态。实现序列化的类需要实现`Serializable`接口,...

    java 序列化代码示例

    Java序列化是Java平台中的一种标准机制,它允许将对象的状态转换为字节流,以便存储、传输或恢复。在Java中,一个类如果要实现序列化,需要实现`Serializable`接口,这是一个标记接口,不包含任何方法。下面我们将...

    java 反序列化利用工具marshalsec-0.0.3-SNAPSHOT-all

    java -cp target/marshalsec-0.0.1-SNAPSHOT-all.jar marshalsec.<Marshaller> [-a] [-v] [-t] [<gadget_type> []] 参数说明: -a:生成exploit下的所有payload(例如:hessian下的...

    java序列化实现演示

    Java序列化是Java平台中的一种标准机制,允许对象的状态被保存到磁盘或者在网络中进行传输,以便在后续的时间或地点恢复这些对象。这个过程包括两个主要操作:序列化(将对象转换为字节流)和反序列化(将字节流恢复...

    aip-java-sdk-4.1.0.zip )

    同时,注意到还有一个名为"json-20160810.jar"的依赖文件,这是JSON库,用于数据序列化和反序列化,是与百度服务器进行通信时传输数据的关键工具。 要实现图片文字识别,开发者需要完成以下几个步骤: 1. **初始化...

    java 序列化成PHP格式。

    将java数据 序列化成PHP的格式 a:4:{s:6:"title2";s:13:"这是标题2";s:6:"title3";s:13:"这是标题3";s:5:"title";s:13:"这是标题1";s:6:"title4";s:13:"这是标题4";} 或者a:1:{i:0;a:1:{s:4:"name";s:10:"这是1321";...

    通过实例深入了解java序列化

    通过实例深入了解 Java 序列化 Java 序列化是 Java 系列技术中一个较为重要的技术点,用于将 Java 对象序列化为二进制文件。开发人员只需要了解被序列化的类需要实现 Serializable 接口,使用 ObjectInputStream 和...

    Java序列化(Serializable)与反序列化-.docx

    Java序列化(Serializable)与反序列化_.docx

    Java序列化(Serializable)与反序列化-.pdf

    Java序列化(Serializable)与反序列化_.pdf

    java序列化和反序列化

    ### Java序列化与反序列化详解 #### 一、Java序列化概述 Java序列化(Serialization)是一项重要的功能,它可以将对象的状态转化为一系列字节,从而实现对象的持久化存储或在网络上传输。序列化机制使得Java对象...

    java serializable 序列化与反序列化

    **一、Java序列化** 1. **什么是序列化**:序列化是将对象的状态(属性和成员变量)转换为可以存储或传输的数据格式的过程。在Java中,通常是将对象转换为字节数组,以便写入磁盘或通过网络发送。 2. **为什么需要...

    java对象序列化Demo------------Serializable

    java 序列化 对象 Serializable 写着玩的Demo 简单 实用

    weblogic 漏洞统计 CVE

    2. CVE-2016-3416、CVE-2016-0688、CVE-2016-0638:这些是2016年的高知名度漏洞,可能使攻击者能够通过恶意构建的请求执行任意代码,通常与反序列化问题有关。 3. CVE-2015-2623、CVE-2015-4744:这些漏洞可能允许...

    「业务安全」书安-第四期_java反序列化 - 安全漏洞.zip

    【Java反序列化安全漏洞详解】 Java反序列化是一个常见的编程操作,用于将序列化的对象状态转换回其原始形式,以便在程序的不同部分之间传递或存储。然而,这个过程也带来了一种潜在的安全风险,即Java反序列化安全...

    Java实现序列化例子

    Java序列化是Java平台提供的一种将对象转换为字节流,以便存储到磁盘、数据库或网络中的机制。它是Java语言内置的一种特性,主要用于持久化数据,也可以在进程间传递对象,或者在网络上传输对象。在Java中,如果一个...

    java对象序列化和反序列化

    Java对象序列化与反序列化是Java编程中重要的概念,主要应用于数据持久化、网络传输以及存储等场景。本文将详细解析这两个概念及其在实际应用中的实现方式。 **一、Java对象序列化** 1. **定义**: Java对象序列化...

    Java 文件 序列化 读写

    Java文件序列化是Java平台中一种重要的数据存储和交换机制,它允许我们将对象的状态转换为字节流,以便可以保存到磁盘、网络传输或在内存中存储,然后在需要时将这些字节流恢复为原来的对象。这个过程称为序列化...

    java反序列化利用程序UI版Beta1.1.rar

    1. **Java序列化机制**:Java对象序列化是通过实现`Serializable`接口来标记一个类可被序列化。`ObjectOutputStream`用于将对象写入流,`ObjectInputStream`用于从流中读取并反序列化对象。 2. **易受攻击的库**:...

Global site tag (gtag.js) - Google Analytics