類型信息僅在編譯時需要生成正確的字節碼。字節碼指令(如彙編指令)通常只能對一種數據類型起作用。因此,使用的指令反映了操作數的類型。大多數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
所以我們存儲和使用istore
和iload
加載整數,然後我們將它們添加使用iadd
(i
爲整數)。
現在拿這個例子中,採用了動態內存分配,而不是原始的:
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的答案中的參考。
這是否涉及內存中的表示?我認爲這在很大程度上取決於實施。事實上,我認爲一旦JVM加載了一個被確定爲* valid *的類文件,嚴格來說,它不必將這些信息與實際的實例數據一起「存儲」。這與執行無關。當實例被內省(例如反射)時,則可以在班級數據中查找該信息。並且...那裏是:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-FieldType – Marco13
我不知道這個問題的答案,但在彙編語言中,一段數據被解釋爲一個指針,或者作爲面值,由作用於該數據的指令的類型決定。將此擴展到Java,我猜測當Java將代碼編譯爲字節碼時,它會編譯字節碼指令以將引用類型視爲指向其他內存位置的指針,並將基本類型視爲面值。儘管這是一個完整的猜測。 – jrahhali
好的。因此,大致JVM實現可以將20字節的連續數據存儲在內存中,哪個字節應該被解釋爲int,哪些字節應該被解釋爲double-part1,並且double-part2會被從類中引用?或者可以使用特定於JVM的性能來處理它..好的。 – Teddy