[讨论] java 类型所占用的字节数

xgj1988 2011-05-20
JVM好像写的是一个LONG 基本类型是 8个字节。Integer是4个字节。

那我现在得到的结果好像并非如此。。
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;

@SuppressWarnings("unused")
public class Test {
	private static ArrayList<Integer> permGen = new ArrayList<Integer>();
	private byte[] bytes = new byte[(1024 << 10) * 10];

	public static void main(String[] args) throws Exception {
		String x = new String("123");
		long y=4L;
		NullOutputStream out = new NullOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(out);
		oos.writeObject(y);
		System.out.println(out.size());

	}

 
	private static class NullOutputStream extends OutputStream {

		int size = 0;

		public void write(int b) throws IOException {
			size++;
		}

		public void write(byte[] b) throws IOException {
			size += b.length;
		}

		public void write(byte[] b, int off, int len) {
			size += len;
		}

 
		public int size() {
			return size;
		}
	}
}





我得到的结果是y是82.这个。但是对于String(123)可以得到10。这个和和预计的一样 首先String 是个对象,对象本身就是4个字节,加上"123".length()*2,可以得到10 。
但是对于y的long类型,结果是82,太让我出乎意料了。
xgj1988 2011-05-20
额。好像是方法调用错了。 用writeLong是4,感觉是引用所占的字节 ,先看看源代码。
RednaxelaFX 2011-05-20
嗯你这是典型的错误。我记得以前在哪帖里回复过的…啊啊那个也应该打捞到blog里的。
序列化之后的数据跟原本在JVM内的Java对象运行时的样子没有直接关系。

你测的数据只是序列化后数据的大小。那是符合Java序列化机制所规定的,而跟JVM规范没关系。

================================================

举个简单的一个例子来说明差别:
Java说Java程序要用UTF-16作为内部编码来存储String的内容。那么运行时JVM内String里真正装字符串数据的可以是一个char[]
(注意:但也可以不是char[];byte[]的实现也有,请看JDK 6 update 23里的j2se/src/share/altclasses/java/lang/String.java)。

但是ObjectOutputStream却是用UTF-8编码来输出字符串的。看writeUTF方法的描述。

================================================

所以说别用序列化的办法来看Java对象的大小。
非要从Java层面看的话,java.lang.instrument.Instrumentation.getObjectSize(Object objectToSize) 这个才是正道。
xgj1988 2011-05-20
3Q。以前真还没仔细研究过。这个
Global site tag (gtag.js) - Google Analytics