使用计算总内存大小的方法确定jvm中为对象分配的存储空间大小

来源:互联网 发布:电信运营商数据 编辑:程序博客网 时间:2024/04/30 09:56

最近发现产品的java程序,占用内存变大很多。由于是从之前的32位server转到使用64位server,所以很有可能是不同架构下jvm分配内存大小不同导致的。

JAVA中没有类似C语言的sizeof函数,所以要确定jvm为基本类型或特定对象分配的内存大小,看起来比较困难。

下面的代码通过新建大量Object计算内存总大小的方式,来确定为每个对象分配的内存大小。

public class Sizeof{public static void main (String [] args) throws Exception{testMem(1);testMem(2);testMem(3);}    private static void testMem (int index) 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 oneString testObj="";int x = 1;long y = 1;String z = "";        for (int i = -1; i < count; ++ i)        {            Object object = null;                        // Instantiate your data here and assign it to object                        object = new Object ();switch (index) {case 1: object = new Integer (x);testObj="Integer"; break;case 2: object = new Long (y);testObj="Long"; break;case 3: object = new String (z);testObj="String"; break;            }            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 = Math.round (((float)(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");System.out.println(testObj + " 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.currentThread ().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

分别在32位和64位server上编译执行上面的程序,得到的结果:

32位server

Integer size=16 bytes
Long size=16 bytes
String size=24 bytes

64位server

Integer size=24 bytes
Long size=24 bytes
String size=40 bytes

可见,同样的class文件在不同架构的jvm执行下,会占用不同大小的内存空间。看来64位的系统也不一定好。。。

原创粉丝点击