2012-04-30 61 views
5

我想知道在內存中爲對象分配的真實空間。對象,數組和基元類型的Java和精確引用大小

我試圖用例子來解釋:使用64位JVM,指針大小應該是8個字節,所以:

  • Object singletest = new Object();將採取8個字節,以引用對象加在對象的大小
  • Object arraytest = new Object[10];將8字節來引用,其中陣列存儲位置加8 * 10個字節來存儲陣列加上每個對象的大小
  • int singleint = new int;將採取僅有2個字節,因爲int是原始類型
  • int[] arrayint = new int[10];將採取8個字節,以引用位置和10 * 2個字節用於元件

此外,這是爲什麼Java允許寫這樣的代碼的原因:

int[][] doublearray = new int[2][]; 
int[0][] = new int[5]; 
int[1][] = new int[10]; 

真正發生的事情是,數組會像對象一樣產生一個引用(aka指針),所以它在聲明時並不關心第二維的大小(並且維度可以不同,它們之間沒有鏈接) 。然後將佔用的空間爲:參考doublearray(8字節),第一維僅僅是對第二維的引用,所以其他8個字節* 2(第一維大小),最後2個字節* 5加2個字節* 10.

所以,最後,如果有一個真正的階級是這樣的:

class Test { 
    int a, b; 
    int getA() {return A}; 
    void setA(int a) {this.a = a;} 
    int getB() {return B}; 
    void setB(int b) {this.b = b;} 
} 

當我調用一個新的實例,一個指針(或命名爲參考,因爲它的Java)的8個字節會使用加2 + 2字節將整數存儲到類中。

問題是:我是對的還是我寫了廢話?此外,當我沒有實例化一個對象,但我只是聲明它,8個字節將被分配給進一步使用或不?而如果我分配一個空值?

同時對於原始類型我很確定只是聲明它將分配所需的空間(如果我聲明一個「int i」,那麼我可以立即調用i ++,因爲沒有引用被使用,只設置了一部分內存在「0」)。

我在互聯網上搜索沒有聰明的迴應...我知道我寫了很多問題,但任何幫助將不勝感激! (也許我不是唯一一個有興趣)

+0

可能的重複[是否有一個簡單的方法來獲取java對象的大小?](http://stackoverflow.com/questions/8775865/is-there-a-simple-way-to-get -Java-object大小) –

回答

8

使用的是64位JVM,指針大小應爲8個字節,

實際上其通常爲32位,除非你有一個最大堆大小32 GB或更多的堆。這是因爲Java使用引用而不是指針(每個對象位於8字節而不是1邊界)

JVM可以根據您使用的JVM和最大堆大小來更改引用的大小。

對象singletest =新對象();將需要8個字節來引用對象加上對象的大小

該對象將使用大約16個字節的堆。它可能會或可能不會使用4個字節的堆棧,但它可以只使用一個寄存器。

對象ArrayTest中=新對象[10];

這將使用大約16個字節用於報頭,加10倍的基準尺寸(總共約56字節)

INT singleint =新INT;將只有2個字節,因爲int是一個基本類型

int總是32位位,你不能創建一個new原始。從概念上講,它可能使用4個字節的堆棧,或者它只能使用一個寄存器。

INT [] arrayint =新INT [10];將8個字節,以引用位置和10 * 2個字節用於元件

再次對象很可能是大小相同new Object[10](56字節)

int[][] doublearray = new int[2][]; 
int[0][] = new int[5]; 
int[1][] = new int[10]; 

我不會稱它爲的doubleArray,因爲它可能與double[]

混淆然而大小likkely爲約16 + 2 * 4 doublearray和16 + 5 * 4 + 4(用於填充)和16 + 10 * 4

在堆上分配的內存與8字節的邊界對齊。

我調用一個新的實例化一個8字節的指針(或者它引用的名字,因爲它是Java)將被加2 + 2字節用於將整數存儲到類中。

基準是在堆棧上,通常這是不包括在內。

該對象具有大約16個字節的標頭,int值佔用2 * 4個字節。

當我不實例化一個對象,但我只是聲明它

的Java不會讓你聲明的對象,只有原語和引用。

如果我分配一個空值?

這可能會改變引用的值,但沒有任何反應。

如果我聲明一個「INT I」,那麼我可以立即調用我++,因爲沒有參考被使用,只是的存儲器的一部分被設置好的上的「0」

否堆將被使用,可能不會使用堆棧(可能是4個字節)。可能JIT編譯器會刪除代碼,如果它沒有做任何事情。

也許我不是唯一一個有興趣的

...但不要太害怕問。 ;)

+0

謝謝! :)這是我徘徊的那種迴應!我正在註釋每一個字! :) – pierpytom

+0

PS:我真的與「新詮釋」錯了,我剛剛意識到,我寫了「新詮釋」的真實...我混淆了32位int與16位大小,但「新詮釋」... – pierpytom

+1

你有任何機會的C + +背景? ;)即使對於有經驗的Java開發人員來說,64位JVM可以使用32位引用並且經常這樣做的事實可能令人驚訝。 –