该文章会的简要目录如下:

  • Serialization的概述
  • 用‘transient’进行性能优化
  • 关键点总结

Serializtion的概述

Serializtion是将一个完整的JAVA对象写入输出流的过程,这个流可以是文件,字节数组或者TCP/IP相关的Socket流。

Deserializtion就是反序列化,也就是说将一个完整的JAVA对象从输入流里读取出来。

JAVA类必须如果实现 java.io.Serializable或 java.io.Externalizable 接口,也可以继承实现了这些接口的超类。那么此JAVA对象就被序列化或者反序列化了。

所以的基本数据类型和一些JAVA API类都是进行了序列化的,你不必要进行额外的序列化。

如果你使用Externalizable可以定制你的序列化方式。这篇文章主要关注的是Serializtion接口

Serializable接口是一个标志位接口,他没有任何的接口方法。像EJB,RMI,ATG这些主流的JAVA技术都是基于序列化进行对象传输的,这些技术本身都暗中的将你的对象进行了序列化的操作。。

下面两个方法可以使对象写入流或者从流中读取对象。

ObjectInputStream.readObject();                    // to read object

ObjectInputStream.writeObject(Object obj);  // to write object

序列化机制

当你用序列化从网络中读或者写一个对象到文件中去的时候,这个完整对象意味着对象本身以及他的初始化变量,还有超类的变量。Transient的排除在外。你可以看一下下面这幅图来加深理解。

 

在这个类关系视图下,当我将CorporateEmployee对象写入到文件中去的时候,会先初始化Address, 再初始化SecondAddress,然后调用Employee,最后再调用到CorporateEmployee本身。这样一个完整的对象就被加载完毕。通过这种加载方式,你会发现,他会将写入所有的东西直到类关系走完。

用‘transient’进行性能优化

如果变量用transient进行修饰的话,此变量就会被输入流或者输出量直接忽略,这样的一个好处就是我们可以通过使用trsnsient来避免一些不必要的数据写入流里。

下面是一段测试代码:

public class SerializationTest {
	static long			start, end;

	OutputStream		out			= null;
	InputStream			in			= null;
	OutputStream		outBuffer	= null;
	InputStream			inBuffer	= null;
	ObjectOutputStream	objectOut	= null;
	ObjectInputStream	objectIn	= null;



	public Person getObject() {
		Person p = new Person("SID", "austin");
		Vector v = new Vector();
		for (int i = 0; i < 7000; i++) {
			v.addElement("StringObject" + i);
		}
		p.setData(v);
		return p;
	}
	public static void main(String[] args) {
		SerializationTest st = new SerializationTest();
		start = System.currentTimeMillis();
		st.writeObject();
		st.readObject();
		end = System.currentTimeMillis();
		System.out.println("Time taken for writing and reading :" + (end - start) + "milli seconds");

	}
	public void readObject() {
		try {
			in = new FileInputStream("c:/temp/test.txt");
			inBuffer = new BufferedInputStream(in);
			objectIn = new ObjectInputStream(inBuffer);
			objectIn.readObject();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (objectIn != null)
				try {
					objectIn.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}

	}



	public void writeObject() {
		try {
			out = new FileOutputStream("c:/temp/test.txt");
			outBuffer = new BufferedOutputStream(out);
			objectOut = new ObjectOutputStream(outBuffer);
			objectOut.writeObject(getObject());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (objectOut != null)
				try {
					objectOut.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}

	}
}

public class Person implements Serializable {

	private String	name;
	private Vector	data;
	private String	address;

	public Person(String name, String address) {
		this.name = name;
		this.address = address;
	}

	public String getAddress() {
		return address;
	}

	public Vector getData() {
		return data;
	}

	public String getName() {
		return name;
	}


	public void setData(Vector data) {
		this.data = data;
	}

}

执行这段代码,会得到以下结论:

Time taken for writing and reading :96milli seconds

如果此时将“private Vector data”改为“ private transient Vector data;”再执行这段代码,你会发现:

Time taken for writing and reading : 31milli seconds

 

关键点总结

1.使用transient关键字将不需要进行序列化的数据忽略。

2.当你在使用RMI,EJB,ATG等技术时,请使用JAVA Serialiable内建的序列来传输对象,同时配合transient关键字进行变量过滤。

2 thoughts on “JAVA序列化的浅析与性能优化(Best Practice about Serialization)”
  1. I’m not sure exactly why but this website is loading very slow for me. Is anyone else having this problem or is it a issue on my end? I’ll check back later and see if the problem still exists.

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注