2012-11-09 57 views
1

可能重複:
Size of a byte in memory - JavaJava中的字節默認情況下需要4個字節?

我在一篇文章中閱讀。我只是按照原樣粘貼:

  • 該類佔用至少8個字節。所以,如果你說**new Object();**你會在堆上分配8個字節。
  • 每個數據成員佔用4個字節,long和double除外,佔8個字節。即使數據成員是一個字節,它仍然會佔用4個字節!另外,所使用的存儲器的數量在8個字節塊中增加。所以,如果你有一個包含一個字節的類,那麼 將佔用該類的8個字節和數據的8個字節,總共16個 字節(呻吟!)。

是真的Java字節分配/佔用4字節嗎?空類需要8個字節? 它在這裏也是令人困惑的。

+2

也許鏈接實際的文章會有用嗎? – hd1

回答

2

這是錯誤的,至少對於HotSpot JVM。在那裏,類中的原始字節字段將佔用一個字節,但是類的實例的大小始於8字節,並且字段被分組爲每個字節需要八個字節的塊 - 例如,您可以不跨8字節邊界分割字段。

參見例如http://www.codeinstructions.com/2008/12/java-objects-memory-structure.html

+0

+1所以'Byte'對象將佔用16個字節,因爲這是最小的。 –

+0

http://www.ibm.com/developerworks/library/j-codetoheap/根據這篇文章,一個實例從12個字節開始。 – hakunami

+0

@hakunami該文章指定了不同JVM實現的數字。我的號碼對於HotSpot是正確的。 –

5

由於Java規範沒有強制使用內存,這取決於您使用的JVM實現。

當然,在所有JVM實現中(例如實現運行時類型檢查)都會有每個對象的開銷。 JVM可能選擇內存對齊字段(在某些平臺上,訪問該字段時會顯着加速)。但是,如果數組成員爲內存對齊填充,並且可以確認(至少在oracle的vm for windows上)布爾值[]每個元素需要一個字節,那麼我會大吃一驚。

另外,值得注意的是,如果您碰巧遇到一個適當大的堆,引用類型字段的大小可以是8個字節。

總結:如果您真的想知道,請測量目標JVM上的內存消耗。

編輯:出於好奇,我寫了一個小的(不準確)基準:

class FourBytes { 
    byte a,b,c,d; 
} 

public class Test { 

    long usedBefore = used(); 

    long used() { 
     return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 
    } 

    public void before() { 
     System.gc(); 
     usedBefore = used(); 
    } 

    public void after(String text) { 
     long usedAfter = used(); 
     System.out.println(text + "\t" + new BigDecimal(usedAfter - usedBefore).movePointLeft(6) + " bytes"); 
     before(); 
    } 

    { 
     int max = 1000000; 
     before(); 
     boolean[] bools = new boolean[max]; 
     after("boolean in array"); 

     char[] chars = new char[max]; 
     after("char in array "); 

     Object[] objects = new Object[max]; 
     after("reference type in array"); 

     for (int i = 0; i < max; i++) { 
      objects[i] = new Object(); 
     } 
     after("Object instance "); 

     Byte[] bytes = new Byte[max]; 
     before(); 
     for (int i = 0; i < max; i++) { 
      bytes[i] = new Byte((byte) i); 
     } 
     after("Byte instance "); 


     Integer[] integers = new Integer[max]; 
     before(); 
     for (int i = 0; i < max; i++) { 
      integers[i] = new Integer(i); 
     } 
     after("Integer instance"); 

     FourBytes[] fbs = new FourBytes[max]; 
     before(); 
     for (int i = 0; i < max; i++) { 
      fbs[i] = new FourBytes(); 
     } 
     after("FourBytes instance"); 

    } 

    public static void main(String[] args) throws Exception { 
     new Test(); 
    } 
} 

java version "1.7.0_02" 
Java(TM) SE Runtime Environment (build 1.7.0_02-b13) 
Java HotSpot(TM) Client VM (build 22.0-b10, mixed mode, sharing) 

它打印:

boolean in array 1.183624 bytes 
char in array  2.091768 bytes 
reference type in array 4.091768 bytes 
Object instance  8.023664 bytes 
Byte instance  16.133408 bytes 
Integer instance 16.147312 bytes 
FourBytes instance 16.142568 bytes 
+0

+1爲基準 –

+0

+5爲基準! :-) –

3

類佔用至少8個字節。所以,如果你說new Object();你將在堆上分配8個字節。

在OpenJDK的/熱點JVM它將使用的32位JVM 8個字節和16個字節的64位的JVM。

每個數據成員佔用4個字節,long和double除外,佔8個字節。

最小尺寸是1個字節而不是4個字節。即使在64位JVM上,引用也使用4個字節。

即使數據成員是一個字節,它仍然會佔用4個字節!

這是一個新想法。我不知道你會如何得出這個結論。

另外,使用的存儲器數量增加了8個字節塊。

從技術上講,它與8字節邊界對齊。

所以,如果你有一個包含一個字節一個類會佔用8個字節的類

它會佔用在32位或64位的頭8首或12個字節位JVM加上字節的1個字節,然後四捨五入到下一個8字節的邊界。

和8個字節的數據,總共16個字節(呻吟!)。

確實,但是每個可能的Byte對象都被緩存和自動裝箱,所以沒有理由這麼做。你永遠不需要明確地或甚至隱式地創建一個字節。

Byte b = new Byte((byte) 1); // bad idea. 
Byte b = 1; // simpler and more efficient 
byte b = 1; // the most efficient option.