2016-08-02 21 views
4

如果堆中有一個對象,並且該對象有幾個實例變量,則某些是基本類型,而其他對象很少。所以,如果這個對象有5個字段,那麼這個對象在內存中是如何構造的?具體來說...... Java在哪裏存儲每個字段的數據類型?有一些「標誌字節」和一些「數據字節」,其中「標誌字節」標識接下來的幾個「數據字節」的數據類型?Java如何識別某個位置是否擁有原語或引用

我指的是一些額外的細節出發超出了這個答案: https://stackoverflow.com/a/19623603/1364747

這個答案拋出的如何數據本身存儲在內存中有更詳細的: https://stackoverflow.com/a/1907455/1364747

但它仍然不說標誌存儲在哪裏,說數據類型是int/long/double/float/reference。

+3

這是否涉及內存中的表示?我認爲這在很大程度上取決於實施。事實上,我認爲一旦JVM加載了一個被確定爲* valid *的類文件,嚴格來說,它不必將這些信息與實際的實例數據一起「存儲」。這與執行無關。當實例被內省(例如反射)時,則可以在班級數據中查找該信息。並且...那裏是:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-FieldType – Marco13

+0

我不知道這個問題的答案,但在彙編語言中,一段數據被解釋爲一個指針,或者作爲面值,由作用於該數據的指令的類型決定。將此擴展到Java,我猜測當Java將代碼編譯爲字節碼時,它會編譯字節碼指令以將引用類型視爲指向其他內存位置的指針,並將基本類型視爲面值。儘管這是一個完整的猜測。 – jrahhali

+0

好的。因此,大致JVM實現可以將20字節的連續數據存儲在內存中,哪個字節應該被解釋爲int,哪些字節應該被解釋爲double-part1,並且double-part2會被從類中引用?或者可以使用特定於JVM的性能來處理它..好的。 – Teddy

回答

1

下面是一個更具體的答案,我恐怕仍然不回答你的問題所有。下面是從Java 7個文檔的鏈接,與相關部門是「2.11指令集彙總」:https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html

我會複製粘貼&有些是:

2.11.1。類型和Java虛擬機

大部分的Java虛擬機指令,指令集對他們執行的操作 編碼類型的信息。對於 實例,iload指令(§iload)將本地 變量的內容(必須是int)加載到操作數堆棧中。指令(§fload)與float值相同。這兩個指令可能具有相同的實現,但具有不同的 操作碼。

對於大多數類型的指令,所述指令類型是用一個字母在操作碼助記符顯式地表示 :ⅰ用於 INT操作,升長,S爲短,B爲字節,C爲焦炭,F對於 浮點數,d表示double,a表示參考。

2.11.2。加載和存儲指令Java虛擬機 幀的局部變量 (§2.6.1)和操作數堆棧(§2.6.2)之間

的加載和存儲指令傳輸值(§2.6 )。

訪問對象字段和數組元素的指令 (§2.11.5)也可以向操作數堆棧和從操作數堆棧傳送數據。

還有很多。有趣的閱​​讀。

+0

謝謝。這很清楚。我一直把它當作灰色地帶。我將通讀文檔以獲得更多的理解。 – Teddy

1

類型信息僅在編譯時需要生成正確的字節碼。字節碼指令(如彙編指令)通常只能對一種數據類型起作用。因此,使用的指令反映了操作數的類型。大多數C族語言都是如此。

爲了看到在使用原語和動態分配時字節碼會有什麼不同,我們舉一個簡單的例子。

public static void main (String [] args) { 
    int i = 0; 
    int j = i + 1; 
} 

而生成的字節碼:

public static void main(java.lang.String[]); 
    Code: 
    0: iconst_0 
    1: istore_1 
    2: iload_1 
    3: iconst_1 
    4: iadd 
    5: istore_2 
    6: return 

所以我們存儲和使用istoreiload加載整數,然後我們將它們添加使用iaddi爲整數)。

現在拿這個例子中,採用了動態內存分配,而不是原始的:

public static void main (String [] args) { 
    Integer i = new Integer(0); 
    int j = i + 1; 
} 

而且字節碼:

public static void main(java.lang.String[]); 
    Code: 
    0: new   #2     // class java/lang/Integer 
    3: dup 
    4: iconst_0 
    5: invokespecial #3     // Method java/lang/Integer."<init>":(I)V 
    8: astore_1 
    9: aload_1 
    10: invokevirtual #4     // Method java/lang/Integer.intValue:()I 
    13: iconst_1 
    14: iadd 
    15: istore_2 
    16: return 

在這個版本中,我們首先要調用的intValue()方法Integer對象檢索值,然後我們可以通過iadd對其執行操作。

並且爲了證明數據類型不需要在編譯後存儲(因爲它們在指令本身編碼,如istore用於「整數存儲」),請參閱jrahhali的答案中的參考。

相關問題