在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

解决方案 »

  1.   

    这是一个对齐的问题。我在c++中遇到过。其实应该是一样的。http://dev.csdn.net/Develop/article/42/42446.shtm
    看一下吧。
      

  2.   

    to  lsrj(小孬) :
    感觉跟对齐没关系吧。
    每次只测试一个类型。在第一个for循环中i = -1,因为,在分配第一个对象时可能jvm初始化类时,作了分配前期工作,
    占了一些额外的空间,所以将第一个分配的对象忽略掉,在分配第一个对象之后才计算已用的空间。
      

  3.   

    这个例子写的很好,正好说明了java中基本类型封装对象所占内存的大小.
    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个字节根本没有被使用.呵呵,仔细分析了一晚,还是有很多收获的.
      

  4.   

    to lsrj(小孬):
      不好意思,果然跟对齐有关。to laughsmile(海边的星空) :
      谢谢你的分析。目前java中似乎没必要sizeof,以后一定会派上用场的。