1. 程式人生 > >Java 基本數據類型 sizeof 功能

Java 基本數據類型 sizeof 功能

float nvi ndb running ring from sizeof 精確 details

Java 基本數據類型 sizeof 功能

來源 https://blog.csdn.net/ithomer/article/details/7310008

技術分享圖片

Java基本數據類型
int 32bit
short 16bit
long 64bit
byte 8bit
char 16bit
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)

根據http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html官方文檔的描述:

boolean: The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn‘t something that‘s precisely defined.

布爾類型:布爾數據類型只有兩個可能的值:真和假。使用此數據類型為跟蹤真/假條件的簡單標記。這種數據類型就表示這一點信息,但是它的“大小”並不是精確定義的。

可以看出,boolean類型沒有給出精確的定義,《Java虛擬機規範》給出了4個字節,和boolean數組1個字節的定義,具體還要看虛擬機實現是否按照規範來,所以1個字節、4個字節都是有可能的。這其實是運算效率和存儲空間之間的博弈,兩者都非常的重要。

Java基本數據類型大小

public class Calcsizeof {
    
    private void calcSize() {
        System.out.println("Integer:" + Integer.SIZE/8); // Integer:4
        System.out.println("Short:" + Short.SIZE/8); // Short:2
        System.out.println(
"Long:" + Long.SIZE/8); // Long:8 System.out.println("Byte:" + Byte.SIZE/8); // Byte:1 System.out.println("Character:" + Character.SIZE/8); // Character:2 System.out.println("Float:" + Float.SIZE/8); // Float:4 System.out.println("Double:" + Double.SIZE/8); // Double:8 // System.out.println("Boolean:" + Boolean.toString(false)); } public static void main(String[] args) { Calcsizeof calcsizeof = new Calcsizeof(); calcsizeof.calcSize(); } }

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.
long freeMemory()
Returns the amount of free memory in the Java Virtual Machine.
void gc()
Runs the garbage collector.
static Runtime getRuntime()
Returns the runtime object associated with the current Java application.
long maxMemory()
Returns the maximum amount of memory that the Java virtual machine will attempt to use.
void runFinalization()
Runs the finalization methods of any objects pending finalization.
使用這些簡單的內存訪問,可以得到內存的一些情況,我們通過建立一個大的某個類的數組,來查看內存用了多少,進而可以求得類的大小。

源碼:

public class Calcsizeof {

    private static long usedMemory() {
        Runtime rTime = Runtime.getRuntime();
        return rTime.totalMemory() - rTime.freeMemory();
    }

    private static void runGC() {
        Runtime rTime = Runtime.getRuntime();
        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 void calcSize2() {
        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(); // Object size = 8 // ? 16
            // obj = new Integer(i); // Object size = 16 // ? 16
            // obj = new Short((short)i); // Object size = 16 // ? 16
            // obj = new Long(i); // Object size = 16 // ? 24
            // obj = new Byte((byte)0); // Object size = 16 // ? 16
            // obj = new Character((char)i); // Object size = 16 // ? 16
            // obj = new Float(i); // Object size = 16 // ? 16
            // obj = new Double(i); // Object size = 16 // ? 24
            // obj = new Boolean(false); // Object size = 16 // ? 16
            // obj = new String(); // Object size = 40 // ? 24

            if (i < 0) {
                obj = null;
                runGC();
                heap1 = usedMemory();
            } else {
                objs[i] = obj;
            }
        }

        runGC();
        long heap2 = usedMemory();
        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 void calcSize() {
        System.out.println("Integer:" + Integer.SIZE/8);
        System.out.println("Short:" + Short.SIZE/8);
        System.out.println("Long:" + Long.SIZE/8);
        System.out.println("Byte:" + Byte.SIZE/8);
        System.out.println("Character:" + Character.SIZE/8);
        System.out.println("Float:" + Float.SIZE/8);
        System.out.println("Double:" + Double.SIZE/8);
        // System.out.println("Boolean:" + Boolean.toString(false));
    }

    public static void main(String[] args) {
        Calcsizeof calcsizeof = new Calcsizeof();
        // calcsizeof.calcSize();
        calcsizeof.calcSize2();
    }
}

控制臺輸出內容:

>java -cp out\production\Test Calcsizeof
heap1 = 1099096; heap2 = 2700368
heap2 - heap1 = 1601272; Integer size = 16


註意:Object[] objects = new Object[count];
只是分配了數組空間,沒有分配對象的空間。數組中只有引用而已。

結論:下代碼測試基本對象時,得出的結果象下面:

Object obj = null;
// obj = new Object(); // Object size = 8
// obj = new Integer(i); // Object size = 16
// obj = new Short(i); // Object size = 16
// obj = new Long(i); // Object size = 16
// obj = new Byte(i); // Object size = 16
// obj = new Character(i); // Object size = 16
// obj = new Float(i); // Object size = 16
// obj = new Double(i); // Object size = 16
// obj = new Boolean(false); // Object size = 16
// obj = new String(); // Object size = 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字節.
還有4個字節根本沒有被使用.呵呵,仔細分析了一晚,還是有很多收獲的

====================== End

Java 基本數據類型 sizeof 功能