} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
在系列化之前,将密码字段加密,然后系列化到硬盘,在反系列化时,通过类D中的readObject(ObjectInputStream in)做解密操作,确保了数据的安全。
如:RMI 技术是完全基于Java 序列化技术的,服务器端接口调用所需要的参数对象来至于客户端,它们通过网络相互传输。这就涉及RMI 的安全传输的问题。一些敏感的字段,如用户名密码(用户登录时需要对密码进行传输),我们希望对其进行加密,这时,就可以采用本节介绍的方法在客户端对密码进行加密,服务器端进行解密,确保数据传输的安全性。
【序列化存储规则】
请看如下代码:
view plain
package wen.hui.test.serializable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
*
* @author whwang 2011-12-1 下午11:00:35
*/
public class Test5 {
public static void main(String[] args) {
ObjectOutputStream out;
try {
out = new ObjectOutputStream(new FileOutputStream(
"obj"));
A t = new A();
// 试图将对象两次写入文件
out.writeObject(t);
out.flush();
System.err.println("加入第一个类:" + new File("obj").length());
//t.a = 10;
out.writeObject(t);
out.close();
System.err.println("加入第二个类:" + new File("obj").length());
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
"obj"));
// 从文件依次读出两个文件
A t1 = (A) oin.readObject();
A t2 = (A) oin.readObject();
oin.close();
// 判断两个引用是否指向同一个对象
System.err.println(t1 == t2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
对同一对象两次写入文件,打印出写入一次对象后的存储大小和写入两次后的存储大小,然后从文件中反序列化出两个对象,比较这两个对象是否为同一对象。一般的思维是,两次写入对象,文件大小会变为两倍的大小,反序列化时,由于从文件读取,生成了两个对象,判断相等时应该是输入false 才对。但实际结果是:第二次写入对象时文件只增加了5 字节,并且两个对象是相等的,这是为什么呢?
解答:Java 序列化机制为了节省磁盘空间,具有特定的存储规则,当写入文件的为同一对象时(根据包名+类名),并不会再将对象的内容进行存储,而只是再次存储一份引用,上面增加的5 字节的存储空间就是新增引用和一些控制信息的空间。反序列化时,恢复引用关系,使得程序 中的t1 和t2 指向唯一的对象,二者相等,输出true,该存储规则极大的节省了存储空间。
但需要注意,在上面程序中将//t.a = 10注释打开,执行的结果也一样。 原因就是第一次写入对象以后,第二次再试图写的时候,虚拟机根据引用关系知道已经有一个相同对象已经写入文件,因此只保存第二次写的引用,所以读取时,都是第一次保存的对象
作者 SMCwwh