2014-11-14 40 views
1

我試着找到它,但是我沒有關於術語的適當知識,也無法真正在Google上提出正確的問題。關於內存分配的一些問題

第一:我在做類似的樹,一個結構,其中一個對象有地圖的孩子,同爲孩子和未來......

public class Attribute 
{ 
    private String key; 
    private int value; 
    private HashMap<String, Attribute> modifiers; 

    public Attribute(String key, int value) 
    { 
     this.key = key; 
     this.value = value; 
    } 
} 

修飾符實際上當你把東西在它只是初始化(使用c的局部無效方法)。在JUST聲明中使用HashMap多少內存(如果是)?(如上面的代碼中所示)?

第二:玩家是ofc。播放器對象,存儲播放器的所有數據。

public class Something 
{ 
    private Player player; 

    public Something() {} 

    public Something(Player player) 
    { 
     this.player = player; 
    } 
} 

1:類似的問題,如果我打電話Something(),是不是初始化PLAYER對象使用一些內存,多少錢?我在某處讀到,當你聲明'某事'時,內存是根據這個'某事'的類型分配的。但它如何與對象一起工作? 2:如果我打電話給Something(Player player),並且由於我正在對已經存在的對象進行引用,那麼這個引用使用多少內存? (this.PLAYER =播放器) 我猜這樣的引用就像指針一樣,但是它使用了多少內存,它對於Java中的所有對象都是不變的?

+1

首先,使用Java約定。 'ALL_CAPS'用於常量。其次 - 不要擔心。空地圖的開銷很小,除非你有數千萬個對象,否則不值得考慮。 – chrylis 2014-11-14 22:35:28

回答

0

對象需要幾分鐘(應該是32左右的地方,但高度依賴於JVM版本,系統,...)字節的內存,即使你創造一個非常空new Object()

class SomeClass { 
    Object someField; 
} 

如果向該類添加一個字段,該對象的每個實例都需要有空間用於對另一個對象的額外引用。一個引用大致是一個內存地址,應該需要4或8個字節。引用的對象有多大並不重要。

class SomeClass { 
    Object someField = new Object(); 
} 

如果實際引用另一個對象,則對象的大小保持不變。引用的值不再是「0」,它指向某個實際的對象。

但是你顯然會消耗更多的內存,因爲引用的對象也需要在內存中。

如果我打電話new Something()

您將獲得1個Something對象分配,它的大小是基本對象+ 1個參考。 Java永遠不會自動創建一個Player對象。你必須告訴它這樣做。

如果我會打電話new Something(Player player)

你會得到與上面相同的東西,只是存儲在參考值現在指向一些有用的東西。它實際上只是一個4字節的數字字段,最後會有所不同。

1

這是VM依賴。在大多數情況下 - 對於32位Oracle JVM或具有小於〜32GB堆空間的64位Oracle JVM 7+實例 - 將添加4個字節。

無論是空引用還是引用對象(儘管引用的對象都有自己的空間要求),空間使用率是相同的。

這裏有一份來自Oracle's tech notes on JavaSE 7 JVM enhancements

壓縮哎呀

的「空中接力」,還是普通對象指針在Java中熱點的說法,是一個管理對象指針。 oop的大小通常與本地機器指針相同,這意味着LP64系統上的64位。在ILP32系統上,最大堆大小略小於4千兆字節,這對於許多應用程序來說是不夠的。在LP64系統上,給定程序使用的堆可能要比在ILP32系統上運行時大1.5倍左右。這個要求是由於託管指針的擴展大小。內存價格低廉,但是現在帶寬和緩存供應不足,因此顯着增加堆的大小並且僅超過4千兆字節的限制是不理想的。

將Java堆中的指針指向與8字節地址邊界對齊的對象。壓縮的oops將來自64位Java堆基地址的32位對象偏移表示爲託管指針(在許多但並非JVM軟件中的所有位置)。因爲它們是對象偏移量而不是字節偏移量,所以它們可以用於處理多達40億個對象(不是字節),或者堆大小可高達32千兆字節。要使用它們,必須將它們縮放8倍,並將其添加到Java堆基地址以查找它們所引用的對象。使用壓縮oops的對象大小與ILP32模式中的大小相當。

術語解碼用於表示將32位壓縮的oop轉換爲託管堆的64位本地地址的操作。逆操作被稱爲編碼。

在Java SE 6u23及更高版本中默認支持並啓用壓縮的oops。在Java SE 7中,如果未指定-Xmx並且-Xmx值小於32千兆字節,則使用壓縮的oops是64位JVM進程的缺省值。對於6u23發行版之前的JDK 6,請使用java命令的-XX:+ UseCompressedOops標誌來啓用該功能。