在javaworld中看到的一文章,说怎样模拟c中的sizeof函数,当然以下程序只能用来测试小的对象或者基本对象。但是,我在使用以下代码测试基本对象时,得出的结果象下面:
Object类对象是 8字节
Integer类对象是 16字节
Long类对象是 16字节
Byte类对象是 16字节
怎么会这样呢???不解。public class Sizeof
{
public static void main (String [] args) throws Exception
{
// Warm up all classes/methods we will use
runGC ();
usedMemory (); // Array to keep strong references to allocated objects
final int count = 100000;
Object [] objects = new Object [count];
long heap1 = 0; // Allocate count+1 objects, discard the first one
for (int i = -1; i < count; ++ i)
{
Object object = null;
/* Instantiate your data here and assign it to object*/
//object = new Object ();
object = new Integer (i); // ????
//object = new Long (i); //????
//object = new String ();
//object = new Byte( (byte) 0); //????
//object = new Float( 0.2f); //????
//object = new Double( 0); //????
if (i >= 0)
objects [i] = object;
else
{
object = null; // Discard the warm up object
runGC ();
heap1 = usedMemory(); // Take a before heap snapshot
}
} runGC ();
long heap2 = usedMemory (); // Take an after heap snapshot:
final int size = (int)Math.round ( ((double)(heap2 - heap1)) /count);
System.out.println ("'before' heap: " + heap1 +
", 'after' heap: " + heap2);
System.out.println ("heap delta: " + (heap2 - heap1) +
", {" + objects [0].getClass () + "} size = " + size + " bytes"); for (int i = 0; i < count; ++ i) objects [i] = null;
objects = null;
} private static void runGC () throws Exception
{
// It helps to call Runtime.gc()
// using several method calls:
for (int r = 0; r < 4; ++ r) _runGC ();
} private static void _runGC () throws Exception
{
long usedMem1 = usedMemory (), usedMem2 = Long.MAX_VALUE;
for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++ i)
{
s_runtime.runFinalization ();
s_runtime.gc ();
Thread.yield ();
usedMem2 = usedMem1;
usedMem1 = usedMemory ();
}
} private static long usedMemory ()
{
return s_runtime.totalMemory () - s_runtime.freeMemory ();
}
private static final Runtime s_runtime = Runtime.getRuntime ();} // End of class
Object类对象是 8字节
Integer类对象是 16字节
Long类对象是 16字节
Byte类对象是 16字节
怎么会这样呢???不解。public class Sizeof
{
public static void main (String [] args) throws Exception
{
// Warm up all classes/methods we will use
runGC ();
usedMemory (); // Array to keep strong references to allocated objects
final int count = 100000;
Object [] objects = new Object [count];
long heap1 = 0; // Allocate count+1 objects, discard the first one
for (int i = -1; i < count; ++ i)
{
Object object = null;
/* Instantiate your data here and assign it to object*/
//object = new Object ();
object = new Integer (i); // ????
//object = new Long (i); //????
//object = new String ();
//object = new Byte( (byte) 0); //????
//object = new Float( 0.2f); //????
//object = new Double( 0); //????
if (i >= 0)
objects [i] = object;
else
{
object = null; // Discard the warm up object
runGC ();
heap1 = usedMemory(); // Take a before heap snapshot
}
} runGC ();
long heap2 = usedMemory (); // Take an after heap snapshot:
final int size = (int)Math.round ( ((double)(heap2 - heap1)) /count);
System.out.println ("'before' heap: " + heap1 +
", 'after' heap: " + heap2);
System.out.println ("heap delta: " + (heap2 - heap1) +
", {" + objects [0].getClass () + "} size = " + size + " bytes"); for (int i = 0; i < count; ++ i) objects [i] = null;
objects = null;
} private static void runGC () throws Exception
{
// It helps to call Runtime.gc()
// using several method calls:
for (int r = 0; r < 4; ++ r) _runGC ();
} private static void _runGC () throws Exception
{
long usedMem1 = usedMemory (), usedMem2 = Long.MAX_VALUE;
for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++ i)
{
s_runtime.runFinalization ();
s_runtime.gc ();
Thread.yield ();
usedMem2 = usedMem1;
usedMem1 = usedMemory ();
}
} private static long usedMemory ()
{
return s_runtime.totalMemory () - s_runtime.freeMemory ();
}
private static final Runtime s_runtime = Runtime.getRuntime ();} // End of class
看一下吧。
感觉跟对齐没关系吧。
每次只测试一个类型。在第一个for循环中i = -1,因为,在分配第一个对象时可能jvm初始化类时,作了分配前期工作,
占了一些额外的空间,所以将第一个分配的对象忽略掉,在分配第一个对象之后才计算已用的空间。
1.简单的Object对象要占用8个字节的内存空间,因为每个实例都至少必须包含一些最基本操作,比如:wait()/notify(),equals(), hashCode()等
2.使用Integer对象占用了16个字节,而int占用4个字节,说了封装了之后内存消耗大了4倍
3.那么Long看起来比Integer对象应该使用更多空间,结果Long所占的空间也是16个字节.
那么就正好说明了JVM的对于基本类型封装对象的内存分配的规则是如下:
Object所占内存(8个字节)+最大基本类型(long)所占内存(8个字节) = 16字节.
JVM强制使用8个字节作为边界.
所以所有基本类型封装对象所占内存的大小都是16字节.但是还是有区别,比如:Integer对象虽然占用了16个字节的内存,但是只是利用了Object所占内存(8个字节)+int所占内存(4个字节) = 12字节.还有4个字节根本没有被使用.呵呵,仔细分析了一晚,还是有很多收获的.
不好意思,果然跟对齐有关。to laughsmile(海边的星空) :
谢谢你的分析。目前java中似乎没必要sizeof,以后一定会派上用场的。