Java基本数据类型
int ? ? 32bit
short ? 16bit
long ? ?64bit
byte ? ?8bit
int ? ? 32bit
short ? 16bit
long ? ?64bit
byte ? ?8bit
char ? ?16bit
float ? 32bit
double ?64bit
float ? 32bit
double ?64bit
boolean 1bit,This data type represents one bit of information, but its "size" isn't something that's precisely defined.(ref)
Java基本数据类型大小
private static void calSize() { System.out.println("Integer: " + Integer.SIZE/8); // 4 System.out.println("Short: " + Short.SIZE/8); // 2 System.out.println("Long: " + Long.SIZE/8); // 8 System.out.println("Byte: " + Byte.SIZE/8); // 1 System.out.println("Character: " + Character.SIZE/8); // 2 System.out.println("Float: " + Float.SIZE/8); // 4 System.out.println("Double: " + Double.SIZE/8); // 8 // System.out.println("Boolean: " + Boolean); }?Java中模拟c中对sizeof的实现
思路:利用java中GC内存回收前后的heap size差别,得出每个object的大小
?
这是一个程序,java中没有现成的sizeof的实现,原因主要是java中的基本数据类型的大小都是固定的,所以看上去没有必要用sizeof这个关键字。 实现的想法是这样的:java.lang.Runtime类中有一些简单的能涉及到内存管理的函数:
Every Java application has a single instance of class?Runtime?that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the?getRuntime?method.
使用这些简单的内存访问,可以得到内存的一些情况,我们通过建立一个大的某个类的数组,来查看内存用了多少,进而可以求得类的大小。
源码:
private static void calSize2() { runGC(); long heap1 = 0; final int count = 100000; Object[] objs = new Object[count]; for(int i=-1; i<count; i++) { Object obj = null; obj = new Object(); // 8 // obj = new Integer( i ); // 16 // obj = new Short( (short)i ); // 16 // obj = new Long( i ); // 16 // obj = new Byte( (byte)0 ); // 16 // obj = new Character( (char)i ); // 16 // obj = new Float( i ); // 16 // obj = new Double( i ); // 16 // obj = new Boolean( true ); // 16 // obj = new String(); // 40 if(i<0){ obj = null; runGC(); heap1 = usedMemory(); // before memory size } else { objs[i] = obj; } } runGC(); long heap2 = usedMemory(); // after memory size final int size = (int)Math.round( (heap2 - heap1)/(double)count ); System.out.println("heap1 = " + heap1 + "; heap2 = " + heap2); System.out.println("heap2-heap1 = " + (heap2 - heap1) + "; " + objs[0].getClass().getSimpleName() + " size = " + size); for(int i=0; i<count; i++) { objs[i] = null; } objs = null; runGC(); } private static void runGC() { for(int i=0; i<4; i++) { long usedMem1 = usedMemory(); long usedMem2 = Long.MAX_VALUE; for(int j=0; (usedMem1<usedMem2) && (j<500); j++) { rTime.runFinalization(); rTime.gc(); Thread.yield(); usedMem2 = usedMem1; usedMem1 = usedMemory(); } } } private static long usedMemory() { return rTime.totalMemory() - rTime.freeMemory(); }?注意:Object[] objects = new Object[count]; 只是分配了数组空间,没有分配对象的空间。数组中只有引用而已。
?
结论:下代码测试基本对象时,得出的结果象下面: ??
Object obj = null;
obj = new Object(); // 8 obj = new Integer( i ); // 16 obj = new Short( (short)i ); // 16 obj = new Long( i ); // 16 obj = new Byte( (byte)0 ); // 16 obj = new Character( (char)i ); // 16 obj = new Float( i ); // 16 obj = new Double( i ); // 16 obj = new Boolean( true ); // 16 obj = new String(); // 40 怎么会这样呢???解释如下: ?
这个例子写的很好,正好说明了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字节.
|